美文网首页
接口重用:运行时多态与虚函数

接口重用:运行时多态与虚函数

作者: wuzhiguo | 来源:发表于2017-06-15 16:08 被阅读19次

什么是接口?

接口是行为的抽象,接口的目的主要为不同的类提供通用的处理服务,从而实现系统的可维护性与可扩展性。

虚函数、虚指针、虚函数表

编译器对每一个含有virtual函数的类创建一个虚函数表vtable,其实vtable就是一个函数指针数组,vtable中存放该类的类型信息和这个类所有的虚函数地址,而且在这个类中,编译器会隐含的设置一个指向这个虚函数表的虚拟指针vptr。每个类vptr的设定和重置是通过类的构造函数、析构函数和拷贝复制运算符自动完成。vtable中的type_info object就是支持RTTI的,一般放在vtable的第一个位置。

如果不引入虚函数,会怎么样?

虚函数实现运行时多态的机制

代码示例:

class Base {
public:
    Base();
    virtual ~Base() {};
    virtual void test() {
        std::cout << "Base::test" << std::endl;
    }
private:
    int b_i;
};
class Derived : public Base {
public:
    virtual void test() {
        std::cout << "Derived::test" << std::endl;
    }
private:
    int d_i;
};

内存布局:

Paste_Image.png

工作过程:
若是没有虚函数时就不需要中间的vtable间接查找。其中vtable和type_info是放在内存的静态存储区的。vptr的初始化实在类的构造函数中完成,vptr的改写是在类的析构函数中完成。
使用 Base *b = new Derived;b->test();这种通过基类的引用或指针调用虚函数时,编译器先根据指针或引用的的静态类型来判断所调的虚函数是不是属于该类或者它的某个public基类,进行类型检查,然后改写虚函数调用语句,在本例中改写成如下形式

(*(b->vptr[2]))(b);          //b->test();  

记住,vtable是函数指针数组,通过偏移量调用相应的函数。那是怎么调用到这个重写后的test虚函数呢?主要就在vtable的构造和b指针当前所指向的对象。在运行时刻,b指向的是Derived对象,而该对象的vptr指向的是Derived::vtable,这个vtable中存放的是改写后的虚函数地址,而不是Base的虚函数地址。这样就可以正确调用了。
由于调用的时候是根据vtable的偏移量决定,所以函数指针数组中的虚函数指针排列顺序非常重要: 如果一个虚函数在类中是第一次出现,他在vtable中的地址是插入到最后。若果派生类改写了基类的虚函数,这个函数地址在派生类的vtable的位置要和基类中vtable一样(否则通过偏移量找到的不一定是重写的函数地址)。若派生类没有重写基类的虚函数只是单纯继承下来,虚函数在vtable中的位置和基类vtable位置一样。

参考: c++ 虚函数实现多态的原理

相关文章

  • 接口重用:运行时多态与虚函数

    什么是接口? 接口是行为的抽象,接口的目的主要为不同的类提供通用的处理服务,从而实现系统的可维护性与可扩展性。 虚...

  • 深入理解 运行时多态: C++

    1 运行时多态 基于 虚函数, 让 同一 Base ptr / ref ( 同一接口 ) 指向 不同 Deriv...

  • c++虚函数

    说到虚函数,首先要讲一下OOP中的多态,多态简单的说就是一个接口,多种实现. 多态分为编译时多态和运行时多态。编译...

  • 多态,虚函数,纯虚函数,虚函数表

    多态性:一个接口,多种方法.程序在运行时才确定调用的函数,是 oop 的核心概念. 多态性通过虚函数来实现,子类可...

  • 虚函数、纯虚函数

    1.虚函数(impure virtual) C++的虚函数主要作用是“运行时多态”,父类中提供虚函数的实现,为子类...

  • C++第六篇多态

    C++中的多态性分为编译时多态性和运行时多态性,编译时多态通过函数重载和模板体现,运行多态通过虚函数体现编译、连接...

  • C语言模拟实现多态

    C++的多态分为编译时多态的函数重载和运行时的虚函数. 一个基类类型的指针可以指向派生类的对象, 调用虚函数的时候...

  • 查漏补缺

    C++虚函数: 多态: 静态多态(重载)、动态多态(虚函数) 虚函数 虚函数表:编译器为每个类创建了一个虚函数表...

  • 多态与虚函数

    多态与虚函数 注意 在成员函数(静态成员、构造函数和析构函数除外)中调用同类的虚函数的语句是多态的。 在构造函数和...

  • C++虚函数

    C++虚函数 C++虚函数是多态性实现的重要方式,当某个虚函数通过指针或者引用调用时,编译器产生的代码直到运行时才...

网友评论

      本文标题:接口重用:运行时多态与虚函数

      本文链接:https://www.haomeiwen.com/subject/yhewattx.html