Toriyung

导航

C++:虚表指针、虚表、虚函数和动态多态

class Base {
public:
    virtual void show() { std::cout << "Base show" << std::endl; }
};

class Derived_1 : public Base {
public:
    void show() override { std::cout << "Derived show" << std::endl; }
};
class Derived_2: public Base {
public:
    void show() override { std::cout << "Derived show" << std::endl; }
};
Base *b = new Derived_1(); 
b->show(); Base *c = new Derived_2();
c
->show();

 

分析上面代码,用基指针b指向Derived_1的实例化对象,然后使用b调用Derived的实例化对象重写的虚函数show(),同样的创建另外一个基指针调用DErived_2的实例化对象然后调用其重写的show()

那么有个问题,一样时基类Base的指针,它是怎么知道我此时该调用的是Derive_1中的show()还是Derive_2中的show()?

找一个"地图"用来查询,这个"地图"就放在Derived_1和Derived_2类的里面作为它们的成员之一,上面记录着他们各自内部所有的虚函数地址

当调用

b->show();

时,会访问Derived_1中的"地图",找到属于Derived_1的show()函数的地址,然后执行,c->show();同理。

这里的"地图"就是虚表,虚表是一个指针数组,里面存放着该类所有虚函数的地址。

显然,每个类都有自己不同的虚表,那基类指针b是如何得到对应不同的虚表?

当使用多态指针进行类的实例化时,就会"得到"地图,每个基类内都有个成员,称之为虚表指针

当执行

Base *b = new Derived_1(); 

时,b的虚表指针就会初始化为Derived_1实例化对象的虚表地址,或者说指向虚表,这样一来就可以通过虚表指针找到虚表,再进一步找到需要的虚函数

 

 

 

然后就是一个比较重要的问题:为什么必须是指针或者引用才能实现多态?

这里引用一篇博客的实验

简单来说,通过前面的阐述,我们知道多态是通过虚表指针、虚表进行索引查找子类的虚函数,

赋值方式没办法对多态指针(基类指针)进行初始化,也就是说,以下面这种方式

Base b;
Derived_1 bb;
b = bb; 

b内的虚表指针是不会指向bb的虚表,自然无法通过b去调用bb的show函数

posted on 2024-05-29 17:09  Toriyung  阅读(12)  评论(0编辑  收藏  举报