与派生类的虚拟指针混淆

时间:2014-01-08 01:43:39

标签: c++ pointers inheritance

具有虚拟功能的基础,Derived也有一个这样的虚拟功能,

class Base
{
    private:
        int i;
    public:
        Base(int data = 9):i(data)
        {
            cout << "In Base class constructor" << endl;
        }
        void display()
        {
            cout << "In Base class" << endl;
            cout << "i = " << i << endl;
        }
        virtual ~Base()
        {
            cout << "In Base class destructor" << endl;
        }
};

class Derived: public Base
{
    private:
        int j;
    public:
        Derived(int data = 10):Base(11),j(data)
        {
            cout << "In Derived class constructor" << endl;
        }
        virtual void display()
        {
            cout << "In Derived class" << endl;
            cout << "j = " << j << endl;
        }
        ~Derived()
        {
            cout << "In Derived class destructor" << endl;
        }
};

现在在gdb中我看到Derived类对象的总大小是16个字节(int + int + _vptr + _vptr),但是当我在gdb中打印每个对象时我感到困惑,对于基类它显示为这样

$1 = {_vptr.Base = 0x401010, i = 11}这很好,但是对于派生它显示的是这样的

$2 = {<Base> = {_vptr.Base = 0x401010, i = 11}, j = 10}

我没有看到派生类的虚拟指针。根据我的理解,除了继承的基类虚拟指针之外,派生类中还应该有一个虚拟指针指向它自己的虚拟表。我在这里做错了什么还是有其他方法可以得到它?

3 个答案:

答案 0 :(得分:4)

派生类有自己的vtable。因此,该类型的对象具有指向它的单个指针。 vtable包含指向Base成员函数的条目(如果它们未被覆盖)。因此,在Base类型的对象中不需要指向Derived vtable的指针。

_vptr.Base中出现Derived的原因是因为您没有覆盖任何功能。编译器不为vtable生成Drived,因为它只是Base的副本。

答案 1 :(得分:1)

使用单继承,通常只有一个虚函数指针:它指向类似函数指针数组的东西。基类提供的条目数是已知的,派生类只是将自己的虚函数标记到最后。

当然,虚函数表实际上如何工作完全取决于各自的ABI。您可以查看,例如,在Linux上使用的Itanium C++ ABI,也可能在其他系统上使用。

答案 2 :(得分:1)

派生类没有指向其vtable的单独的附加指针 - 而是从基类继承的vtable指针将被覆盖以指向派生类的vtable作为派生类的构造函数运行(后来在析构函数运行时还原)。

这样,当在Base*Base&上对嵌入在构造的派生对象中的Base成员进行操作时,指向VDT的指针(通常偏移到Base对象)允许调度派生类的方法。