0

有没有比以下更好的方法来建立对象数据成员的位置偏移?

class object
{
  int a;
  char b;
  int c;
};

object * o = new object();
int offset = (unsigned char *)&(object->c) - (unsigned char *)o;
delete o;
4

4 回答 4

3

在这种情况下,您的类是 POD,因此您可以使用offsetof来自<cstddef>.

实际上,在大多数实现中,对于大多数类,您可以使用 offsetof 通常使用的相同技巧:

int offset = &(((object *)0)->c) - (object *)0;

无需实际创建对象,尽管您可能不得不抵制一些编译器警告,因为这不能保证有效。

还要注意,如果您的类有任何多重继承,那么(至少)除了一个基类之外的所有类,(void*)(base*)some_object != (void*)(derived*)some_object. 所以你必须小心你应用偏移量。只要您计算并相对于指向实际定义该字段的类的指针应用它(也就是说,不要试图从派生类指针中计算出基类字段的偏移量),您几乎肯定会美好的。没有关于对象布局的保证,但大多数实现都以明显的方式做到这一点。

从技术上讲,对于任何非 POD 类,谈论字段与基指针的“偏移量”是没有意义的。对于该类的所有对象,指针之间的差异不需要相同。

于 2009-11-05T02:15:13.303 回答
2

无需实际创建对象:

(size_t)&(((object*)0)->c)

也就是说,对象中地址为零的成员的地址是该成员在对象中的偏移量。

当然,您需要访问该成员,因此您需要将其设为 astruct或添加public:访问修饰符。

这就是offsetof实现的方式,至少对于大多数编译器而言。

于 2009-11-05T02:19:42.343 回答
2

而不是指针。
您可以使用指向成员的指针。

class X;
typedef int X::*    PtrToMemberInt;  // Declare a pointer to member.

class X
{
    int a;
    char b;
    float c;

    public:
    static PtrToMemberInt   getAPtr()
    {
        return &X::a;
    }

    int d;
};

int main()
{
    // For private members you need to use a public method to get the address.
    PtrToMemberInt aPtr = X::getAPtr();

    // For public members you can take the address directly;
    PtrToMemberInt dPtr = &X::d;


    // Use the pointer like this:
    X   a;
    a.*aPtr = 5;
    a.*dPtr = 6;
}
于 2009-11-05T05:55:35.513 回答
0

为了补充 Martins 的答案,如 Stroustrup 的“C++ 的设计和演变”(第 [13.11] 节)所述:

指向数据成员的指针已被证明是一种在实现中表达 C++ 类布局的有用方法 [Hübel, 1992]

Sandeep 非常友好地转换了原始论文并在http://sandeep.files.wordpress.com/2008/07/ps.pdf上提供

请注意,实现描述早于 C++ RTTI,但我偶尔仍然使用指向成员的东西。

于 2009-11-05T09:44:22.637 回答