我有一个包含一些数据成员的自定义类。我有一个指向类中某个数据成员的指针,我希望有一个指向其封闭实例的指针。例如:
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类型,因此offsetof宏并不总是有效/它会发出编译警告。
是否可以获得指向MyClass实例的指针?
答案 0 :(得分:3)
使用定义良好的C ++不能这样做,因为不相关类型之间的转换是未定义的行为。
实际上,您可能会假设某个类的第一个成员的地址与通过系统上指针的大小偏移的类的地址相同。 (这个指针是你的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
个实例。
答案 1 :(得分:1)
不,这在标准C ++中是不可能的。 offsetof
是执行此类操作的唯一可移植方式,它仅适用于标准布局类。如果它不起作用(或者你不能压制并忽略警告),那你就不走运了。
答案 2 :(得分:1)
CONTAINING_RECORD
是可能适合您的宏,它经常与链表一起使用,其中指向下一个和上一个项的指针嵌入在另一个结构中。