【问题标题】:Confusion with virtual pointer of derived class与派生类的虚拟指针混淆
【发布时间】:2014-01-25 22:54:48
【问题描述】:

Base 有一个虚函数,而 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 中,我看到派生类对象的总大小为 16 字节(int+int+_vptr+_vptr),但是当我在 gdb 中打印每个对象时,我感到很困惑,对于基类,它显示如下

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

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

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

【问题讨论】:

  • type = 是什么?
  • 我刚刚使用 ptype 从 gdb 打印。不是实际代码
  • 还有为什么析构函数使用int
  • 显示逐字代码,而不是任何代码。
  • @Sarath,好吧,据我所知,gdb 看起来喝醉了

标签: c++ pointers inheritance


【解决方案1】:

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

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

【讨论】:

  • 你是说如果我没有覆盖那些派生类 _vptr 也指向基础 vtable?
  • @Sarath,没有。 Derived 的 vtable 将包含指向与 Bases vtable 中的条目相同的功能的条目。但是 vtable 是分开的。
  • 对不起,如果我让情况变得更糟,无论如何我可以在 gdb 中看到该指针,目前我在打印对象时无法查看它。
  • @Sarath,就像 Dietmar 所说,vtable 的实际结构及其功能将取决于 ABI。您需要它来重新解释指针并理解它。与其在调试器中检查代码来了解这一点,我建议您寻找一个资源来解释如何在 C++ 中以某种抽象的级别实现动态调度。
  • @Sarath,我重读了您的问题并理解您的困惑。请查看我的编辑。
【解决方案2】:

对于单继承,通常只有一个虚函数指针:它指向类似于函数指针数组的东西。基类贡献的条目数是已知的,派生类只是将自己的虚函数标记到末尾。

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

【讨论】:

  • 感谢 ABI 链接:我以前使用的链接停止工作了。
【解决方案3】:

派生类没有一个单独的、额外的指向其 vtable 的指针 - 相反,从基类继承的 vtable 指针将被 覆盖 以指向派生类的 vtable 作为派生类的构造函数运行(然后在析构函数运行时恢复)。

这样,当在 Base*Base&amp; 上对嵌入在构造的派生对象中的 Base 成员执行操作时,指向 VDT 的指针会被看到(在 Base 对象的通常偏移处)允许分派给派生类的方法。

【讨论】:

    猜你喜欢
    • 2016-06-07
    • 2012-01-27
    • 2017-07-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-18
    • 2011-09-07
    • 2011-08-15
    相关资源
    最近更新 更多