为什么static_cast为同一个对象提供不同的内存位置?

InQ*_*ive 3 c++ inheritance static-cast memory-address

我的代码

class Parent { int a; };
class Child { int b; };
struct GrandChild : public Parent, public Child { int a, b, c; };

int main() {
    GrandChild GC;
    std::cout << "GrandChild's address is at : " <<&GC<<endl;
    std::cout << "Child's address is at : " <<static_cast<Child*>(&GC)<<endl;
    std::cout << "Parent's address is at : " <<static_cast<Parent*>(&GC)<<endl;

}
Run Code Online (Sandbox Code Playgroud)

输出:

GrandChild's address is at : 0077F6F8
Child's address is at : 0077F6FC
Parent's address is at : 0077F6F8
Run Code Online (Sandbox Code Playgroud)

为什么在static_cast之后内存位置有如上所述的不一致?

Rem*_*eau 13

GrandChild来自两者ParentChild.因此,GrandChild存储器中ParentChild对象由其内存中的对象和对象组成.

&GC它本身返回GrandChild整个对象的内存地址

static_cast<Parent*>(&GC)返回对象Parent内部分的起始地址GrandChild.

static_cast<Child*>(&GC)返回对象Child内部分的起始地址GrandChild.

在您的情况下,GrandchildParent第一个派生,因此该Parent部分在GrandChild内存块的开头对齐.然后该Child部分跟随该Parent部分.以下是一个说明:

结构体


Bri*_*ian 5

&GCGrandChild对象的地址GC.static_cast<Child*>(&GC)是的地址Child 子对象GC.而且static_cast<Parent*>(&GC)是地址Parent 子对象GC.

在你的特定实现中,似乎一个GrandChild对象以一个Parent子对象开始,然后是Child子对象,因此Parent子对象的地址与完整GrandChild对象的地址相同,但是Child子对象的第一个字节不是整个对象的第一个字节GrandChild,所以它的地址更高.但是,您不能依赖这种可移植的行为; 不同的实现可以以不同的顺序分配基类和成员子对象,甚至不需要在不同的类之间保持一致.

  • @VictorPolevoy一个`GrandChild`对象本身包含一个`Parent`对象和一个`Child`对象.碰巧在OP的编译器上,`Parent`对象在`GrandChild`对象的最开头分配.它们共享一个内存块,因为`Parent`对象是*GrandChild`对象的真正*部分. (2认同)
  • @VictorPolevoy:您似乎不理解基类对象实际上是派生类对象的一部分.`Parent`子对象(包括它的`a`成员)与`GrandChild`对象的数据一样多,也就是声明的3个成员(`a`,`b`和`c`)的一部分.类定义.你似乎期望`GrandChild`对象的地址不在`GrandChild`对象的开头(这将与`Parent`子对象的地址重合),而是在中间的某个地方(其中)在'GrandChild`类中声明的成员位于). (2认同)