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

Get pointer to enclosing instance from member pointer

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

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?

class不是POD类型,所以offsetof宏并不总是work/it给出编译警告。

是否可以获得指向 MyClass 实例的指针?

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

您不能使用定义明确的 C++ 执行此操作,因为在不相关的类型之间进行转换是未定义的行为。

实际上,您可能会假设 class 的第一个成员的地址与 class 偏移指针大小的地址相同在你的系统上。 (这个指针是你的 v-table 的实现,并且在 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 实例。

CONTAINING_RECORD 是可能适合您的宏,它经常与链表一起使用,其中指向下一个和上一个项目的指针嵌入到另一个结构中。