2

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

#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;
}

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

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

但随后出现编译错误,这意味着pba实际上并不指向 type 的对象CDerived。那么这里发生了什么?内存泄漏?

4

2 回答 2

10

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

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

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

于 2012-08-29T12:28:55.527 回答
0

sizeof返回对象的静态类型的大小,因为pba是 a ,所以是CBase*的静态类型,其大小是(无数据成员和 a )。\*pbaCBase8vfptr

[...] 意思是 pba 实际上并不指向 CDerived 类型的对象

确实如此,但您不能通过CDerived指向CBase.

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

于 2012-08-29T12:28:54.547 回答