【问题标题】: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 指针调用哪个函数。

标签: c++ inheritance polymorphism


【解决方案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++ 标准中没有定义所需的行为)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-10-29
        • 2015-10-24
        • 2013-08-25
        • 1970-01-01
        • 2014-08-27
        • 1970-01-01
        • 2011-11-16
        • 2020-09-30
        相关资源
        最近更新 更多