我对多态性的一个方面感到困惑。请考虑以下代码:
#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
字节。 CDerived
指向的pba
对象的其他16个字节发生了什么变化?我也试过这个:
std::cout << "pba->a = " << pba->a << std::endl;
但是后来出现了编译错误,这意味着pba
实际上没有指向CDerived
类型的对象。那么这里发生了什么?内存泄漏?
答案 0 :(得分:10)
sizeof
是一个编译时构造。它无法知道运行时类型,因此它只考虑编译时类型,即CBase&
。
pba->a
由于类似原因而无法编译:{{1}}的编译时类型为pba
,而CBase*
没有CBase
会员。这就是静态类型语言的工作原理。如果要使用a
成员,则需要一个类型为CDerived
的变量(或引用或指向它的变量)。
但是, CDerived
对象仍然存在。您可以看到,如果将指针转换为指向CDerived
的指针,例如CDerived
。
答案 1 :(得分:0)
sizeof
返回对象静态类型的大小,由于pba
是CBase*
,因此*pba
的静态类型为CBase
,其大小为8
(无数据成员和vfptr
)。\
[...]意思是pba实际上并没有指向CDerived类型的对象
确实如此,但您无法通过指向CDerived
的指针访问CBase
个特定成员。
假设我将您移至CBase*
并告诉您访问该成员a
。你不能。您无法确定它是指向CDerived
的指针,并且具有该成员,或者某个其他派生类(除非您使用RTTI)。 逻辑上没有意义通过基类指针访问派生类成员。