从成员指针获取指向封闭实例的指针

Get pointer to enclosing instance from member pointer

本文关键字:指针 实例 取指 成员 获取      更新时间:2023-10-16

我有一个带有一些数据成员的自定义类。我有一个指针指向类的数据成员之一,我想有一个指针指向它的封闭实例。例如:

class MyClass{
public:
    int a;
    int b;
    virtual ~MyClass(){//because MyClass is not POD type
    }
};
...
int* aptr = ...; //something valid, and i know its a pointer to a MyClass::a member
MyClass* classptr = ?; //how can i get a pointer to the class instance?

类不是POD类型,所以宏的偏移量并不总是工作/它给出编译警告。

有可能得到一个指向MyClass实例的指针吗?

您不能使用定义良好的c++来做到这一点,因为不相关类型之间的强制转换是未定义的行为。

在现实中,您可能会假设类的第一个成员的地址与系统中指针大小偏移的类的地址相同。(这个指针是v表的实现,这在c++实现中是相当一致的。)然后,如果您对数据成员的打包做了一些假设,那么您可以手动调整指针,以便从一个数据成员移动到另一个数据成员。offsetof是另一种技术,可以在这里帮助您,但在您的上下文中仍然没有定义好。

要么用特定的编译器断言来破坏源代码(因为您限制了可移植性),要么采用不同的技术。我当然会采用后者。

这里有一些非常糟糕的代码,告诉你如何做到这一点。考虑
struct Foo
{
    virtual ~Foo(){}; /*introduce a v-table*/
    int n;
};

,

  Foo foo;
  foo.n = 0xdeadbeef; // To test
  int* p = &foo.n; // Suppose this is our pointer.
  char* pp = (char*)(void*)p; // This cast is undefined behaviour.
  pp -= 8; // Skip over 64 bit v-table. More undefined behaviour.
  Foo* ph = (Foo*)(pp); // Yet more undefined behaviour.

ph指向Foo实例

不,这在标准c++中是不可能的。offsetof是做这种事情的唯一可移植的方法,它只适用于标准布局类。如果它不起作用(或者您无法抑制和忽略警告),那么您就不走运了。

CONTAINING_RECORD是可能为您工作的宏,它经常与链表一起使用,其中指向下一项和上一项的指针嵌入在另一个结构体中。