派生类的虚拟表,除了父类一个虚函数之外没有任何虚函数

Posted

技术标签:

【中文标题】派生类的虚拟表,除了父类一个虚函数之外没有任何虚函数【英文标题】:Virtual table for the derived class which is not having any virtual function except parent class a virtual function 【发布时间】:2015-08-27 09:19:57 【问题描述】:

将为不具有任何虚函数的派生类创建虚拟表,但父类是一个未被派生类覆盖的虚函数。

例如:

class A
public:
    virtual void show();

;

class B : public A


;

B类的虚表怎么样。

【问题讨论】:

哪个编译器?标准 C++ 不知道 vTable 是什么。 你为什么关心这个?它有什么不同? 我只是对虚拟表以及我们需要虚拟表来实现动态多态性的所有情况感到好奇。 我认为我们也需要 B 类的虚拟表。如果我们继承类 B 并覆盖函数 show,则它是必需的。在这种情况下,我们需要一个虚拟表来确定我们必须在运行时使用基类 A 指针调用哪个函数。 【参考方案1】:

您的问题没有标准答案。它实际上取决于编译器版本。 C++ 中没有指定标准 ABI。如果您有更深入的兴趣,请查看“Itanium C++ ABI”或尝试通过查看汇编代码自行找到答案。

甚至有人提议为 C++ 定义可移植 ABI

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4028.pdf

【讨论】:

【参考方案2】:

这是使用 g++ (Ubuntu 8.2.0-1ubuntu2~18.04) 8.2.0 编译时 gdb 所说的内容

15  class A
16  
17      public:
18          virtual void show()
19  ;  
20  
21  class B:public A
22  
23  ;  
24  
(gdb) l
25  int main()
26  
27      A a;
28      B b;
29  
(gdb) p a 
$5 = _vptr.A = 0x55555575f5c8 <vtable for A+16>
(gdb) p b 
$6 = <A> = _vptr.A = 0x55555575f5b0 <vtable for B+16>, <No data fields>
(gdb) 

因此,至少在这种情况下,我们可以得出结论,基类和派生类具有不同的 vtable。

【讨论】:

【参考方案3】:

您可以通过查看对象的内容来检查它。我编写了这个简单的程序,它打印基类、派生类和与基类相同但使用普通方法而不是虚拟方法的类的内容:

#include <iostream>
#include <string>
#include <iomanip>

using namespace std;

class Base 
public:
    virtual void show() 
;

class Derived : public Base
 ;

class NonVirtual 
public:
    void show() 
;

struct Test

    int data1, data2;
;

template <typename T>
void showContents(T* obj, string name)

    Test* test = new Test;
    test = reinterpret_cast<Test*>(obj);
    cout << name << ": " << hex << "0x" << test->data1 << " " << "0x" << test->data2 << endl;
    delete test;


int main()

    Base* base = new Base;
    Derived* derived = new Derived;
    NonVirtual* nonVirtual = new NonVirtual;

    showContents(base, "Base");
    showContents(derived, "Derived");
    showContents(nonVirtual, "NonVirtual");

    delete base;
    delete derived;
    delete nonVirtual;

Live demo


上面的程序用cpp.sh编译后运行的结果(我不确定那里用的是什么编译器):

Base: 0x4013e0 0x0
Derived: 0x401400 0x0
NonVirtual: 0x0 0x0

所以我希望这意味着确实为 Derived 对象创建了一个虚拟表(至少对于这个编译器 - 因为 C++ 标准中没有定义所需的行为)。

【讨论】:

以上是关于派生类的虚拟表,除了父类一个虚函数之外没有任何虚函数的主要内容,如果未能解决你的问题,请参考以下文章

探索c++虚函数表

虚函数与作用域

C++中,子类会继承父类的虚函数表!对于父类的析构函数(虚函数) 也会继承吗?

深入理解C++ 虚函数表

[ C++ ] 抽象类 虚函数 虚函数表 -- C++多态

关于C++的虚函数在父类的内部调用