多态性
(一)定义:
一个接口,多个方法,程序在运行时才决定调用的函数(同一事物在不同场景下的多种形态)
(二)分类:
- 静态多态
函数重载
泛型编程
- 动态多态
虚函数
(三)目的:
接口重用,封装可以使得代码模块化,继承可以扩展已存在的代码,以上两种都是为了代码重用,而多态则是为了实现接口重用。
1、静态多态
函数重载算是静态多态,静态多态是编译器在程序编译期间完成的,根据参数的类型或个数来动态的选择函数执行
int add_num(int a, int b)
{
return a + b;
}
double add_num(double a, int b)
{
return a + b;
}
int main()
{
add_num(10, 20);
add_num(10.0,20);
return 0;
}
2、动态多态
在程序运行时,根据基类的引用指向的对象来确定自己具体应该调用哪一个类的虚函数
函数重写:在子类中定义了一个与父类完全相同的虚函数时,则称子类这个函数的重写将父类的虚函数覆盖掉了。
例如下面的例子,程序在运行时,会根据对象所属的类而调用不同的成员函数:
#include <iostream>
using namespace std;
class Person
{
public:
virtual void Aver_height()
{
cout << "1.6m"<< endl;
}
};
class Child:public Person
{
public:
void Aver_height()
{
cout << "1.3m" << endl;
}
};
void Fun(Person& p)
{
p.Aver_height();
}
int main()
{
Person p;
Child s;
Fun(p);
Fun(s);
system("pause");
return 0;
}
//1.6m
//1.3m
注意:
1、只有类的成员函数才能被定义为虚函数,静态成员函数除外
2、如果在类内只做虚函数的声明,而在类外写具体的定义,则声明前面要写virtual关键字,定义时则不用写
3、基类中定义了虚函数,在派生类中也始终保持该特性。子类的虚函数也要写上virtual关键字
4、构造函数不能定义为虚函数,析构函数建议定义为虚函数
5、友元函数不能是虚函数,这是因为友元根本不是成员函数
6、在成员函数的形参后面写上=0,则该成员函数为纯虚函数。包含纯虚函数的类叫做抽象类,抽象类是不能实例化出对象的,子类继承该基类之后需要进行重写,才能实例化对象。
哪些函数不能定义为虚函数?
- 友元函数,它不是类的成员函数
- 全局函数,及在类外定义的函数
- 静态成员函数,他没有this指针
- 构造函数,拷贝构造函数,以及赋值运算符的重载函数
重写&重定义&重载
重写:
1、两个函数不在同一作用域内,分别在基类和派生类中
2、函数名、参数、返回值均相同
3、基类函数必须有virtual关键字
重定义:
1、不在同一作用域内,分别在基类和派生类中
2、函数名相同
3、只要没有构成重写就是重定义
重载:
1、在同一作用域内
2、函数名相同,其他可以不同,如参数类型个数
3、返回值类型可以不同
动态多态的条件:
- 基类中必须包含虚函数,并且在派生类中一定要对基类的虚函数进行重写
- 通过基类对象的指针或者引用调用虚函数