class 的不完整对象

Incomlete object of class

Base * pba = new Derived; Base * pbb = new Base;

虽然都是Base*类型的指针,但pba实际上指向的是Derived类型的对象,而pbb指向的是Base类型的对象。因此,当使用 dynamic_cast 执行它们各自的类型转换时,pba 指向 class Derived 的完整对象,而 pbb 指向 class Base 的对象,这是一个class 派生的不完整对象。

class Derived 的不完整对象是什么意思?

类型有声明,类型有定义

如果你声明了一个类型,它实际上可能没有被定义:

// declare X
class X;

// define X 
class X { 
  int value;
};

您可以创建一个指向仅已声明的类型的指针,但您不能实例化一个 object 如果它仅被声明——它也必须被定义。 (定义也是声明。)

另外,虽然里面定义了一个类型,但这个类型本身还是不完整的。只有在 full 定义完成后(想想 class 的结束}),它才是一个完整的类型,你可以实例化它。

这可以防止像声明一个 object 来拥有它自己的实例这样的事情。

class Bad {
   Bad other; // Invalid: Bad is still an incomplete type
};

class Good {
   Good * other; // just a pointer is ok, doesn't need type info
};

当然,如果你有一个指向不完整类型的指针,你仍然不能取消引用它,或者通过它调用,因为编译器不知道那里有什么。如果您 使用 指针不仅仅是存储地址,您仍然必须拥有完整的定义。

那有什么大惊小怪的?为什么要声明不完整的类型?

在 header 中,如果您只需要指向 object 的指针,则可以避免包含 object 的 header。这意味着该文件不依赖于实现,任何修改 object header 的人都不需要重新编译您的代码。如果您包含另一个 object 的 header,您(以及包括您在内的任何人)将需要在 header 更改时重新编译。如果它是无偿包含,则会减慢编译时间并在代码库中形成更糟糕的依赖关系图。因此,使用不完整的类型是有益的,即使它增加了一点点复杂性。

Base没有在Derived中声明的成员变量and/or成员方法,因此不完整;由于这种情况经常发生,dynamic_cast 禁止将实际父类型转换为其派生类型。

简单地说:Derived 是一个 Base,但 Base 不是 Derived,并且 dynamic_cast 不会将某些东西转换成它不是的东西。这需要 reinterpret_cast 并且是未定义行为的秘诀。

旁注:

如果您要询问有关 cplusplus.com 中的代码示例的问题,您应该 link 他们。

我在此处 http://www.cplusplus.com/doc/tutorial/typecasting/ 动态转换下找到了您的代码段。