代码之家  ›  专栏  ›  技术社区  ›  Methos

从成员指针获取类/结构对象

c++
  •  2
  • Methos  · 技术社区  · 15 年前

    我有C++的结构

    struct myStruct {
        int a;
        int b;
        int c;
    }; 
    
    myStruct b;
    int *ptr = &b.c;
    

    (我知道我可以使用C中的类似container_Of()的指针算法来实现这一点

    reinterpret_cast<myStruct*>(reinterpret_cast<char *>(ptr) - offsetof(myStruct, c));
    

    5 回复  |  直到 15 年前
        1
  •  5
  •   Daniel Earwicker    15 年前

    也就是说 offsetof

        2
  •  3
  •   nulldevice    15 年前

    因为 ptr 我的结构 . 我只是建议不要这样做!

        3
  •  1
  •   Dan    15 年前

    "offsetof" macro ....

    找到偏移量,使用该&用于备份的指针算法,例如字符*基。

        4
  •  1
  •   Motti    15 年前

    你的 reinterpret_cast 解决方案是实现您想要的目标的标准方法。它必须至少涉及一个强制转换的原因是您要执行的操作本质上是不安全的。显然,并非所有指向 int myStruct 因此,不可能有一种简单的类型安全方式来执行转换。

        5
  •  0
  •   anon anon    15 年前

    你可以使用这样一个事实,当你从一个指向一个基类(不是唯一的基类)的指针进行转换时,编译器会调整指针,使它指向超类的开始。因此,如果您的“c”成员存在于某个基类的开头,您可以执行如下操作:

    struct myStructBase1 { int a; };
    struct myStructBase2 { int b; };
    struct myStructBase3 { int c; };
    
    struct myStruct : public myStructBase1,myStructBase2,myStructBase3 {
        int d;
    };
    
    int main() {
        myStruct my;
    
        int * bptr = &my.b;
        int * cptr = &my.c;
        // The only dirty part in the code...
        myStructBase2 * base2ptr = reinterpret_cast<myStructBase2*> (bptr);
        myStructBase3 * base3ptr = reinterpret_cast<myStructBase3*> (cptr);
    
        // In each (myStruct*) cast the pointers are adjusted to point to the super class.
        cout << &my << endl <<
                (myStruct*) base2ptr << endl <<
                (myStruct*) base3ptr << endl;
        return 0;
    }
    // Output:
    // 0xbfbc779c
    // 0xbfbc779c
    // 0xbfbc779c
    

    这项工作的要求是: 我不确定这是不是真的。

    编辑:当包装器基类是PODs时,它应该保持不变。经过以下修改:

    struct myStructBase1 { int a; virtual void g() {} };
    struct myStructBase2 { int b; virtual void f() {} };
    struct myStructBase3 { int c;  };
    struct myStruct : public myStructBase1,myStructBase2,myStructBase3 {
        int d;
        virtual void h() {}
    };
    

    0xbfa305f4
    0xbfa305f8
    0xbfa305f4
    

    对于c成员,约束仍然有效。因此,一般来说,答案是:是的,有另一种方法。然而,为每个“可逆”成员定义一个基类可能不是明智的方法。。