c++虚函数

2017-08-13  本文已影响0人  狗尾巴草败了

说到虚函数,首先要讲一下OOP中的多态多态简单的说就是一个接口,多种实现.

多态分为编译时多态运行时多态
编译时多态主要体现在函数重载;
运行时多态是指程序在运行时动态地识别对象,实现不同的行为,这是通过虚函数+继承实现的。

虚函数必须是类的非静态成员函数,也不能是构造函数, 访问权限为public, 虽然在语法上设置成 privateprotect 并没有错误,但虚函数的目的是为了实现多态,所以设置成 protectprivate 是没有意义的。

静态成员函数不能是 virtual 函数的原因

  • 静态成员函数可以不通过对象来调用,静态成员函数没有隐藏的this指针;virtual函数只能通过对象来调用,实现需要依靠隐藏的this指针
  • 静态成员函数是在编译时就绑定了,而virtual函数在运行时才进行绑定

构造函数不能是 virtual 函数的原因

  • 首先从设计理念上来说,构造函数不需要设置成 virtual 函数,从实现机制来说,构造函数也无法实现 virtual 函数
  • 构造函数顾名思义就是构建一个对象,而虚函数是动态的识别对象的类型,这个对象属于是基类、派生类还是更深层次的类,这是运行在对象已经存在的基础上的。所以虚函数的调用必须在构造函数调用之后
  • 虚函数的执行依赖于虚函数指针 vptr, 而 vptr 的初始化即让 vptr 指向 虚函数表 V-table 是在构造函数中实现的,所以
    构造函数不能是虚函数

虚函数表 vtable 和虚函数表指针 vptr

C++的虚函数的实现机制依靠的就是 vtablevptr
vtable 实际上就是 virtual 函数的地址表,这张表解决了继承和覆盖的问题
例如:

class A {
public:
        virtual void f();
        virtual void g();
};
class B: public A{
 public:
          virtual void f();
          virtual void h();
};
B::f() A::g() B::h() 0

上面表格则为B的 vtable, 最后一个值如果为1说明还有下一个虚函数表,存在于多重继承的情况下。
B类的内存分布的第一项即是 vptr,该指针指向B的 vtable

注意:

vtable 在编译时期确立, vptr 在运行期确立。

在继承中析构函数一定要被设置成虚函数

如果不设置成虚函数,那么当父类的指针调用子类的对象,该指针调用析构函数,将会调用父类的析构函数,而子类多出的那一部分数据内存将无法被释放。

上一篇 下一篇

猜你喜欢

热点阅读