从系统实现的角度看,多态性分为两种,静态多态性与动态多态性
静态多态性:函数重载、运算符重载(本质上也是函数重载);
动态多态性:在程序运行过程中才动态地确定操作所针对的对象,又称为运行时的多态性,一般通过虚函数(virtual function)实现。
C++通过虚函数与指向基类的指针一起来实现多态:
- 当一个成员函数被声明为虚函数后,其派生类中的同名函数都自动成为虚函数,因此在派生类中重新声明该虚函数时,可以加virtual,也可以不加,但最好加virtual,使程序清晰。
- 如果在派生类中没有对基类中的虚函数重新定义,则派生类继承其直接基类的虚函数。
静态关联:在编译时即可确定其调用的虚函数属于哪一个类,如函数重载与通过对象名调用的虚函数
动态关联:在运行阶段把虚函数和类对象绑定在一起
何时申明虚函数:
- 首先成员函数所在的类是否会作为基类,其次成员函数在类的继承后有无可能被更改功能,如果希望更改其功能的,一般要设为虚函数
- 如果成员函数在类被继承后功能不需要修改,或派生类用不到该函数,则不要把它设为虚函数
- 考虑对成员函数的调用时通过对象名还是基类指针或者引用,若是通过基类指针或引用去访问,则应设为虚函数
- 有时,在定义虚函数时,并不定义函数体(其函数体是空的),只是定义了一个虚函数名,具体功能留给派生类去添加。
使用虚函数,系统有一定的空间开销,当一个类有虚函数时,系统会为该类构造一个虚函数表(一个指针数组,存放每个虚函数的入口地址)
若一个类中有虚函数,则实例化该类时,对象的第一个成员将是一个指向虚函数表的指针。
纯虚函数,抽象类
virtual int f() = 0;//声明纯虚函数
若一个类中有纯虚函数,则该类为抽象类,抽象类不能实例化,只能用作继承基类
View Code
1 #include <iostream> 2 3 using namespace std; 4 5 //定义基类-动物类 6 class Animals 7 { 8 public: 9 Animals();//定义构造函数 10 Animals(int);//带一个参数的构造函数 11 public: 12 int id; 13 public: 14 virtual void Action();//定义成员函数吗,声明为虚函数,用以实现多态 15 }; 16 17 Animals::Animals(){}//实现构造函数 18 Animals::Animals(int id):id(id){}//实现构造函数,初始化成员列表在定义时不指定,函数实现时才指定 19 void Animals::Action()//实现成员函数 20 { 21 cout<<"Animal's action"<<endl; 22 } 23 24 25 //定义派生类-人类 26 class Person:public Animals 27 { 28 public: 29 Person(int,int,int);//定义构造函数,实现时才调用父类构造函数 30 public://成员变量 31 int weight;//体重 32 int height;//身高 33 public://成员函数 34 virtual void Action();//定义成员函数吗,声明为虚函数,用以实现多态 35 }; 36 //实现派生类构造函数,并显示调用基类构造函数 37 Person::Person(int weight,int height,int id):Animals(id) 38 { 39 this->weight = weight; 40 this->height = height; 41 } 42 43 //实现派生类成员函数 44 void Person::Action() 45 { 46 cout<<"person's action: walk"<<endl; 47 } 48 49 //定义派生类-猴类 50 class Monkey:public Animals 51 { 52 public: 53 Monkey(int,int,int);//定义构造函数,实现时才调用父类构造函数 54 public://成员变量 55 int weight;//体重 56 int height;//身高 57 public://成员函数 58 virtual void Action();//定义成员函数吗,声明为虚函数,用以实现多态 59 }; 60 //实现派生类构造函数,并显示调用基类构造函数 61 Monkey::Monkey(int weight,int height,int id):Animals(id) 62 { 63 this->weight = weight; 64 this->height = height; 65 } 66 67 //实现派生类成员函数 68 void Monkey::Action() 69 { 70 cout<<"monkey's action: jump"<<endl; 71 } 72 73 int main() 74 { 75 //定义动物类对象 76 Animals a; 77 //定义动物类指针 78 Animals * pi; 79 pi = &a; 80 //通过指针调用行为 81 pi->Action(); 82 Person b(10,10,0001); 83 pi = &b;//改变指针指向person 84 pi->Action(); 85 Monkey c(10,10,0002); 86 pi = &c;//改变指针指向monkey 87 pi->Action(); 88 return 0; 89 }