2013-02-08 53 views
11

在项目27“有效的C++”的(第3版,第118页),斯科特Meyers表示:派生类对象有多个地址?

class Base { ... }; 
class Derived: public Base { ... }; 
Derived d; 
Base *pb = &d; 

这里我们只是创建一个基类指针指向一个派生类对象,但有时这两个指针不会一样。当出现这种情况时,在运行时将偏移量应用到Derived*指针,以获取正确的Base*指针值。

这最后一个实施例表明,一个单一的对象(例如,Derived类型的对象)可能具有多个地址(例如,当在由Derived*指针指向由Base*指针和其地址指向它的地址) 。

这里有点让人费解。我知道指向基类的指针可以在运行时指向派生类的对象,这称为多态或动态绑定。但派生类对象在内存中是否真的有多个地址?

猜猜我有一些误解在这里。有人可以澄清一下吗?也许这与C++编译器中如何实现多态性有关。

回答

13

试试看:

class B1 
{ 
    int i; 
}; 

class B2 
{ 
    int i; 
}; 

class D : public B1, public B2 
{ 
    int i; 
}; 

int 
main() 
{ 
    D aD; 
    std::cout << &aD << std::endl; 
    std::cout << static_cast<B1*>(&aD) << std::endl; 
    std::cout << static_cast<B2*>(&aD) << std::endl; 
    return 0; 
} 

还有为B1子对象没有可能的方式有相同的 地址作为B2子对象。

4

一个对象只有一个地址;这就是它在内存中的位置。当您创建一个指向基地子对象你得到的子对象的地址,而不必是相同的包含它的对象的地址。一个更简单的例子:

struct S { 
    int i; 
    int j; 
}; 

S s; 

s的地址将是从s.j地址不同。

类似地,基地子对象的地址不必是相同的派生对象的地址。使用单一继承通常是,但是当多重继承发挥作用并且忽略空的基类时,至多其中一个基类子对象可以具有与派生对象相同的地址。因此,当你将一个指向派生对象的指针转换为指向它的一个基地址的指针时,你不一定会获得与派生对象地址相同的值。

+0

“与单继承它通常是” - 你能想到的任何情况下,它*不会*? – us2012 2013-02-08 16:10:04

+4

@ us2012:非多态基类,多态派生类,在派生类中偏移量0处添加的vtable指针,后跟基类。 – MSalters 2013-02-08 16:26:58

+0

@ MSalters很好!谢谢。 – us2012 2013-02-08 16:27:54