多态
- 按字面的意思就是“多种状态”。在面向对象语言中,接口的多种不同的实现方式即为多态。
- 通过晚绑定技术实现,即调用时才确定使用那个函数
如果基类是虚函数,那么子类同名的话就可以动态调用
虚函数的定义要遵循以下重要规则:
-
如果虚函数在基类与派生类中出现,仅仅是名字相同,而形式参数不同,或者是返回类型不同,那么即使加上了virtual关键字,也是不会进行滞后联编的。
-
只有类的成员函数才能说明为虚函数,因为虚函数仅适合用与有继承关系的类对象,所以普通函数不能说明为虚函数。
-
静态成员函数不能是虚函数,因为静态成员函数的特点是不受限制于某个对象。
-
内联(inline)函数不能是虚函数,因为内联函数不能在运行中动态确定位置。即使虚函数在类的内部定义定义,但是在编译的时候系统仍然将它看做是非内联的。
-
构造函数不能是虚函数,因为构造的时候,对象还是一片位定型的空间,只有构造完成后,对象才是具体类的实例。
-
析构函数可以是虚函数,而且通常声名为虚函数。
#include "stdafx.h" #include <iostream> #include <stdlib.h> class CA { public: void f() { cout << "CA f()" << endl; } virtual void ff() { cout << "CA ff()" << endl; f(); } }; class CB : public CA { public : virtual void f() { cout << "CB f()" << endl; } void ff() { cout << "CB ff()" << endl; f(); CA::ff(); } }; class CC : public CB { public: virtual void f() { cout << "C f()" << endl; } }; int main() { CB b; CA *ap = &b; CC c; CB &br = c; CB *bp = &c; ap->f(); b.f(); br.f(); bp->f(); cout << endl; ap->ff(); cout << endl; bp->ff(); cout << endl; int istop; std::cin >> istop; return 0; }
虚函数(virtual):
- 父类函数是虚函数(不是构造函数,构造函数不能为虚函数),析构函数也是虚函数(如果父类不加虚函数标志,那么子类不会析构,造成内存泄露)
- 即可多态,在调用时指针和引用都可以,但是值传递的话,无法实现多态
纯虚函数:
- 虚函数后面加上 = 0;
- 即可构成纯虚函数,这时这个类即为抽象类,抽象类无法实例化
(即有纯虚函数的类即为抽象类,并且派生类也是抽象类) - 所有的函数都为虚函数,那么这个类即为接口类
父类在声明析构函数时候,一定要声明为虚函数,这样在利用多态性时候才不会出现内存泄露。
注意:
- 继承时候,默认是private继承。若需要public继承,则需要加上关键字private
- 指向父类的子类指针,在构造时,父类构造=》子类构造。
析构时,分两种情况:
- 父类析构函数定义为虚函数,则先调用子类的析构函数再调用父类的析构函数
- 父类析构函数不为虚函数时,则直接只调用父类的析构函数。(因为这本来就是只是一个父类的指针)