类的继承——多态的实现原理

本文参照于狄泰软件学院,唐佐林老师的——《C++深度剖析教程》

      • 隐藏的VPTR指针
        • 虚函数调用过程

在C++中用virtual关键字解决了父子间同名覆盖的问题。这也是面向对象中多态的概念。但是,编译器到底如何实现多态的呢?

  1. 当类中声明虚函数时,编译器会在类中生成一个虚函数表
  2. 虚函数表示一个存储成员函数地址的数据结构
  3. 虚函数表是由编译器自动生成与维护
  4. virtual成员函数会被编译器放入虚函数表中
  5. 存在虚函数时,每个对象中都有一个指向虚函数表的指针

类的继承——多态的实现原理_第1张图片

类的继承——多态的实现原理_第2张图片

隐藏的VPTR指针

实际上,当我们用virtual关键字定义虚函数时,C++编译器自动帮我在类中生成了一个VPTR指针指向虚函数表。

示例代码:多态的本质

#include 
#include 
using namespace std;

class Demo
{
protected:
    int mi;
    int mj;
public:
    virtual void print()
    {
        cout << "mi = " << mi << ", "
             << "mj = " << mj << endl;
    }
};

class Derived : public Demo
{
    int mk;
public:
    Derived(int i, int j, int k)
    {
        mi = i;
        mj = j;
        mk = k;
    }

    void print()
    {
        cout << "mi = " << mi << ", "
             << "mj = " << mj << ", "
             << "mk = " << mk << endl;
    }
};
int main()
{
    cout << "sizeof(Demo) = " << sizeof(Demo) << endl;         
    cout << "sizeof(Derived) = " << sizeof(Derived) << endl; 

    return 0;
}

输出结果:
sizeof(Demo) = 12
sizeof(Derived) = 16

问题:编译器是如何调用虚函数的呢?

虚函数调用过程

  1. 编译器首先确认add是否为虚函数。
  2. Yes –> 编译器在对象VPTR所指的虚函数表中查找add()的地址
  3. No –> 编译器直接可以确定调用成员函数的地址

类的继承——多态的实现原理_第3张图片

因此:虚函数的调用效率比普通成员函数要低。在项目中慎用!

你可能感兴趣的:(C++)