多态性和类型转换

Polymorphism and type conversion

本文关键字:类型转换 多态性      更新时间:2023-10-16

我对多态性的一个方面感到困惑。请考虑以下代码:

#include <iostream>
class CBase {
    virtual void dummy() {}
};
class CDerived: public CBase {
    public:
    int a,b,c,d;
    CDerived (): a(1),b(2),c(3),d(4) { }
};
int main () {
    CBase* pba = new CDerived;
    std::cout << "sizeof(CBase) = " << sizeof(CBase) << std::endl; // prints 8
    std::cout << "sizeof(CDerived) = " << sizeof(CDerived) << std::endl; // prints 24
    std::cout << "sizeof(*pba) = " << sizeof(*pba) << std::endl; // prints 8 (?)
    return 0;
}

我的问题如下:在CBase* pba = new CDerived;行上,分配了一个CDerived类型(24字节)的对象,但正如您所看到的,sizeof(*pba) = 8字节。pba指向的CDerived对象的其他16个字节发生了什么情况?我也试过这个:

std::cout << "pba->a = " << pba->a << std::endl;

但随后出现编译错误,这意味着pba确实没有指向CDerived类型的对象。那么这里发生了什么?内存泄漏?

sizeof是一个编译时构造。它不知道运行时类型,所以只考虑编译时类型,即CBase&

pba->a不编译的原因类似:pba的编译时类型是CBase*,而CBase没有a成员。这就是静态类型语言的工作方式。如果要使用CDerived成员,则需要一个类型为CDerived的变量(或指向它的引用或指针)。

但是,CDerived对象仍然存在。您可以看到,如果将指针转换为指向CDerived的指针,就像dynamic_cast<CDerived*>(pba)->a一样。

sizeof返回对象的静态类型的大小,由于pbaCBase*,因此*pba的静态类型是CBase,其大小是8(没有数据成员和vfptr)。\

[…]意味着pba真的不指向经过CDerived 类型的对象

确实如此,但您不能通过指向CBase的指针访问CDerived特定的成员。

假设我将一个CBase*交给您,并告诉您访问成员a。你不能。您不能确定它是指向CDerived的指针,并且具有该成员,或者指向其他派生类(除非使用RTTI)通过基类指针访问派生类成员在逻辑上是没有意义的