c++ - 虚拟的概念

标签 c++ inheritance virtual

我是 CPP 的新手,正在学习后期绑定(bind)多态性。

根据我的阅读和理解,virtual 关键字用于后期绑定(bind)。 它在编译时在内部创建一个由 vptr 指向的 vtable。 所以, 例如

class BASE{
public:
virtual void f1(){cout<<"BASE F1\n";}
virtual void f2(){cout<<"BASE F2\n";}
void f3(){cout <<"BASE F3\n";}
};

class D1:public BASE{
public: 
    virtual void f1(){cout<<"D1 F1\n";}
    void f2(){cout<<"D1 F2\n";}  
};

class DD1:public D1{
public:
    void f1(){cout<<"DD1 F1\n";}
    void f2(){cout <<"DD1 F2\n";}
};

在这里, BASE 将在基类 vtable 中具有 2 个函数:

BASE::f1() 
BASE::f1()

继承自BASE的D1,将继承vtable:

D1::f1()
BASE::f1

DD1 继承自 D1,没有自己的虚表。

当我们创建一个对象时:

//case 1:
BASE *b = new D1(); 
b->f1();//will print "D1 F1"
b->BASE::f1();//will print "BASE F1"
b->f2();//will print "D1 F2"
//case 2:
BASE *b1 = new DD1();
b1->f1();//will print "DD1 F1"
b1->D1::f1();//will print "D1 F1"
b1->BASE::f1();//will print"BASE F1"

但是,以防万一: b1->D1::f1();它给出了一个编译错误

 error: ‘D1’ is not a base of ‘BASE’

问题:为什么?它不应该打印 D1 F1 作为它的虚函数。

在去throw fdump之后,我发现了一件更有趣的事情,有点令人费解;

Vtable for BASE
BASE::_ZTV4BASE: 4u entries
0     (int (*)(...))0
8     (int (*)(...))(& _ZTI4BASE)
16    (int (*)(...))BASE::f1
24    (int (*)(...))BASE::f2

Class BASE
   size=8 align=8
   base size=8 base align=8
BASE (0x7fbc3d2ff120) 0 nearly-empty
    vptr=((& BASE::_ZTV4BASE) + 16u)

Vtable for D1
D1::_ZTV2D1: 4u entries
0     (int (*)(...))0
8     (int (*)(...))(& _ZTI2D1)
16    (int (*)(...))D1::f1
24    (int (*)(...))D1::f2

Class D1
   size=8 align=8
   base size=8 base align=8
D1 (0x7fbc3d31f2d8) 0 nearly-empty
    vptr=((& D1::_ZTV2D1) + 16u)
  BASE (0x7fbc3d2ff180) 0 nearly-empty
      primary-for D1 (0x7fbc3d31f2d8)

Vtable for DD1
DD1::_ZTV3DD1: 4u entries
0     (int (*)(...))0
8     (int (*)(...))(& _ZTI3DD1)
16    (int (*)(...))DD1::f1
24    (int (*)(...))DD1::f2

Class DD1
   size=8 align=8
   base size=8 base align=8
DD1 (0x7fbc3d31f3a8) 0 nearly-empty
    vptr=((& DD1::_ZTV3DD1) + 16u)
  D1 (0x7fbc3d31f410) 0 nearly-empty
      primary-for DD1 (0x7fbc3d31f3a8)
    BASE (0x7fbc3d2ff1e0) 0 nearly-empty
        primary-for D1 (0x7fbc3d31f410)

问题: BASE 类的虚拟表不会被 D1 类继承,D1 类 vTable 和 BASE 类不会被 DD1 继承吗?虚拟表的继承将如何进行?

最佳答案

DD1 which inherits from D1, will not have any vtable of its own.

不,错了。它将拥有自己的 vtable,因为它覆盖了虚函数(这里隐含了 virtual 关键字,因为一旦函数在基类中被声明为 virtual,它在任何地方都是虚的)。

Question: why? should not it print D1 F1 as its virtual function.

b1静态类型Base*,即使它的动态类型是DD1*。因此,您不能调用 b1->D1::f1,因为该语法指示编译器静态解析对函数的调用(同样,静态地)在 b1。如果你绝对想执行这个调用,并且知道 b1 的动态类型实际上是 D1(或派生自它),你可以转换它来改变静态对象类型:

static_cast<D1*>(b1)->D1::f1();

关于c++ - 虚拟的概念,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19199661/

相关文章:

c++ - 如何知道正在使用哪个版本的 openssl boost ssl

java - 继承、 protected 或设置者、获取者

c++ - 如何从多态层次结构中的基类引用调用子类的成员

python - 具有不同接口(interface)的派生类

vb.net - VB.NET 静态变量存储在哪里?

c# - 在方法的开头或结尾调用基方法?

c++ - 有什么方法可以在抽象基类中使用模板函数?

c++ - 无需源代码即可调试/绕过 BSOD

c++ - Qt 和 OpenGL : render a 2D texture

c# - 在 C# 中处理 C++ 结构