如何使用void指针但不是Object来获取对类的成员变量的访问权限

mah*_*esh 1 c++ pointers

我试图在不使用对象的情况下访问类的成员变量.请让我知道如何去做.

class TestMem
{
    int a;
    int b;
public:
    TestMem(){}
    void TestMem1()
    {
        a = 10;
        b = 20;
    }
};

void (TestMem::*pMem)();

int main(int argc, char* argv[])
{

    TestMem o1;
    pMem = &(TestMem::TestMem1);

    void *p = (void*)&pMem;
    // How to access a & b member variables using variable p
    getch();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

Joh*_*ica 5

执行此操作的"正确"方法是使用offsetof()宏来自<stddef.h>.不幸的是,在C++中offsetof()有一些相当严苛的限制:

由于C++中结构体的扩展功能,在这种语言中,使用offsetof限制为"POD [普通旧数据]类型",对于类,或多或少对应于结构的C概念(尽管非派生类)只有公共非虚拟成员函数,没有构造函数和/或析构函数也有资格作为POD).

因此,如果你制作ab公开并摆脱TestMem构造函数,你可以写这样的东西来访问a:

C++风格:

#include <cstddef>

int vala = *reinterpret_cast<int *>(reinterpret_cast<char *>(&o1)
           + offsetof(TestMem, a));
Run Code Online (Sandbox Code Playgroud)

C风格:

#include <stddef.h>

int vala = *(int *) ((char *) &o1 + offsetof(TestMem, a));
Run Code Online (Sandbox Code Playgroud)

请注意,您需要在此使用&o1,而不是p函数指针.地址TestMem::TestMem1不会有任何关系的位置ab.类方法不驻留在类成员变量附近的内存中.


"错误"的方式是猜测内存ab内存.最有可能的是,它们分别位于开始时的偏移0和4 o1.所以这段代码大部分时间都可以工作:

int vala = *(int *) ((char *) &o1 + 0);
int valb = *(int *) ((char *) &o1 + 4);
Run Code Online (Sandbox Code Playgroud)

这里有很多假设.这是假定int为4个字节,并且有之间没有填充ab.另一方面,它没有上面的任何限制:a并且b不需要公开,你可以有一个构造函数,无论如何.