C++的虚函数 Virtual Function

来源:互联网 发布:法语助手软件过期 编辑:程序博客网 时间:2024/06/01 08:52
virtual关键字有两个用处。一个是最常见的: virtual关键字修饰类的成员函数。另一个是虚基类机制,用于多重继承。在定义派生类时,要在基类描述前加关键字virtual。避免内存中父虚基类成员的重复放置。

虚函数:
定义:虚函数必须是类的 非静态成员函数 且 非构造函数,其访问权限是public(可以定义为private or proteceted,但是对于多态来说,没有意义)

作用:是实现动态联编(多态),也就是在程序的运行阶段动态的选择合适的成员函数。通过父类的指针调用实际子类的成员函数。

用法:只需要在声明函数的类体中使用“virtual”将函数声明为虚函数,而定义函数时不需要使用关键字“virtual”。

实现原理:
通过一张虚函数表(Virtual Table)来实现的。每一个类有一个虚表(virtual table),内含该class之中有作用的虚函数的地址,然后每个对象有一个vptr,指向虚表(virtual table)的所在。
C++的编译器应该是保证虚函数表的指针存在于对象实例中最前面的位置(这是为了保证取到虚函数表的有最高的性能——如果有多层继承或是多重继承的情况下)。
1)虚函数按照其声明顺序放于表中。
2)父类的虚函数在子类的虚函数前面。
1)覆盖的f()函数被放到了虚表中原来父类虚函数的位置。
2)没有被覆盖的函数依旧。

虚函数的缺省参数(默认参数):
虽然虚函数是运行期动态绑定的,但是其缺省参数仍然是编译期静态绑定的。所以子类指针在调用父类的函数的时候,缺省参数还是用自己的!

name hiding
派生类中对基类虚函数重写必须把所有重载都重写一遍比如基类中一个虚函数名称是重载的2个函数。那么派生类中若要重写,必须也重写2个。

看看virtual函数和构造函数、静态函数、析构函数、非成员函数、内联函数、友元函数的关系吧!

为什么virtual函数不能是static函数?
static函数都是静态决议的(编译的时候就绑定了),virtual函数是动态决议的(运行时候才绑定)。两个概念是矛盾的。

为什么virtual函数不能是构造函数?
虚函数对应一个vtable,vtable是存储在对象的内存空间的。如果构造函数是virtual的,就需要通过vtable来调用,可是对象还没有实例化,也就是内存空间还没有。这就矛盾了。不过编译是可以通过的。

为什么推荐virtual函数做基类的析构函数?
将基类的析构函数定义为虚函数后,当利用delete释放一个指向派生类(子类)对象的基类(父类)指针时,系统会调用相应的派生类(子类)的析构函数。而如果不将析构函数定义为虚函数时,因为是基类指针,就只调用基类的析构函数。

为什么C++不支持普通函数为虚函数?
      普通函数(非成员函数)只能被overload,不能被override,声明为虚函数也没有什么意思,因此编译器会在编译时邦定函数。

为什么C++不支持内联成员函数为虚函数?
      其实很简单,那内联函数就是为了在代码中直接展开,减少函数调用花费的中断代价,虚函数是为了在继承后对象能够准确的执行自己的动作,这是不可能统一的。(inline函数在编译时被展开,虚函数在运行时才能动态的邦定函数)。但是,虚函数其实是可以声明为inline的,毕竟C++规定在类内部定义的函数都是inline的。但是,你记住,编译器拥有绝地权利来决定是否展开一个inline函数,虽然这么定义了,但是编译器还是去展开它的。

为什么C++不支持友元函数为虚函数?
      因为C++不支持友元函数的继承,对于没有继承特性的函数没有虚函数的说法。

0 0
原创粉丝点击