多态(第三大特征)
c++支持编译时多态(静态多态)和运行时多态(动态多态)
- 运算符重载和函数重载就是编译时多态
- 而派生类和虚函数实现运行时多态。
静态多态和动态多态的区别就是函数地址是早绑定(静态联编)还是晚绑定(动态联编)。如果函数的调用,在编译阶段就可以确定函数的调用地址,并产生代码,就是静态多态(编译时多态),就是说地址是早绑定的。而如果函数的调用地址不能编译不能在编译期间确定,而需要在运行时才能决定,这这就属于晚绑定(动态多态,运行时多态)。
//计算器
class Caculator{
public:
void setA(int a){
this->mA = a;
}
void setB(int b){
this->mB = b;
}
void setOperator(string oper){
this->mOperator = oper;
}
int getResult(){
if (this->mOperator == "+"){
return mA + mB;
}
else if (this->mOperator == "-"){
return mA - mB;
}
else if (this->mOperator == "*"){
return mA * mB;
}
else if (this->mOperator == "/"){
return mA / mB;
}
}
private:
int mA;
int mB;
string mOperator;
};
这种程序不利于扩展,维护困难,如果修改功能或者扩展功能需要在源代码基础上修改
面向对象程序设计一个基本原则:开闭原则(对修改关闭,对扩展开放
//抽象基类
class AbstractCaculator{
public:
void setA(int a){
this->mA = a;
}
virtual void setB(int b){
this->mB = b;
}
virtual int getResult() = 0; //提供一个接口
protected:
int mA;
int mB;
string mOperator;
};
//加法计算器
class PlusCaculator : public AbstractCaculator
{
public:
virtual int getResult() //各类分别实现
{
return mA + mB;
}
};
//减法计算器
class MinusCaculator : public AbstractCaculator{
public:
virtual int getResult(){
return mA - mB;
}
};
//乘法计算器
class MultipliesCaculator : public AbstractCaculator{
public:
virtual int getResult(){
return mA * mB;
}
};
void DoBussiness(AbstractCaculator* caculator){
int a = 10;
int b = 20;
caculator->setA(a);
caculator->setB(b);
cout << "计算结果:" << caculator->getResult() << endl;
delete caculator;
}
说明多态
C++动态多态性是通过虚函数来实现的,虚函数允许子类(派生类)重新定义父类(基类)成员函数,而子类(派生类)重新定义父类(基类)虚函数的做法称为覆盖(override),或者称为重写。
对于特定的函数进行动态绑定,c++要求在基类中声明这个函数的时候使用virtual关键字,动态绑定也就对virtual函数起作用.\
- 为创建一个需要动态绑定的虚成员函数,可以简单在这个函数声明前面加上virtual关键字,定义时候不需要.
- 如果一个函数在基类中被声明为virtual,那么在所有派生类中它都是virtual的.
- 在派生类中virtual函数的重定义称为重写(override).
- Virtual关键字只能修饰成员函数.
- 构造函数不能为虚函数
#include<iostream>
using namespace std;
class animal
{
public:
animal(){}
~animal(){}
virtual void speak() = 0;
};
class cat : public animal
{
public:
cat(){}
~cat(){}
virtual void speak()
{
cout << "cat speak" << endl;
}
};
class dog:public animal
{
public:
dog(){}
~dog(){}
virtual void speak()
{
cout << "dog speak" << endl;
}
};
int main(int argc, char const *argv[])
{
cat c1;
c1.speak();
return 0;
}