代码之家  ›  专栏  ›  技术社区  ›  Å imon Tóth

当通过基指针访问时,编译器如何确定成员的位置

c++
  •  5
  • Å imon Tóth  · 技术社区  · 14 年前

    这件事突然进入我的脑海,我想不出来。

    如果我有这样的代码:

    struct A { char x[100]; };
    
    struct B { int data; };
    
    struct C : A, B {};
    
    #include <iostream>
    using namespace std;
    
    B* get_me_some_stuff()
    {
            static int x = 0;
            if (++x % 2 == 0)
                    return new B();
            else
                    return new C();
    }
    
    int main()
    {
            B* x = get_me_some_stuff();
            B* y = get_me_some_stuff();
    
            x->data = 10;
            y->data = 20;
    
            cout << x->data << " " << y->data << endl;
    
            return 0;
    }
    

    编译器如何确定 data 成员?

    2 回复  |  直到 14 年前
        1
  •  2
  •   kenm    14 年前

    试试这个:

    C* x = new C();
    B* y = x;
    cout << x << " " << y << endl;
    

    我的输出:

    0x1ae2010 0x1ae2074
    

    C* B* (或在另一个方向)包括必要的指针算法。

        2
  •  4
  •   Roger Pate Roger Pate    14 年前

    x和y指针实际上指向B和C对象的B子对象(使用最派生的类型)。

    Example:

    int main() {
      C c;
      B *pb = &c; // converting the pointer here actually adjusts the address
    
      void *pvc = &c; // doesn't adjust, merely type conversion
      void *pvb = pb; // doesn't adjust, merely type conversion
    
      cout << boolalpha;
      cout << (pvc == pvb) << '\n'; // prints false
      cout << (&c == pb) << '\n'; // prints true!
                                  // (&c is converted to a B* for the comparison)
    
      C *pc = static_cast<C*>(pb); // this static_cast, which is UB if pb doesn't
        // actually point to a C object, also adjusts the address
    
      cout << (pc == &c) << '\n'; // prints true
    
      return 0;
    }
    

    重新解释强制转换),并且只能从void转换为最初用于转换为void的完全相同类型:

    reinterpret_cast<C*>(pvb)  // undefined behavior