C++中的多态2
原创
©著作权归作者所有:来自51CTO博客作者CurryCoder的原创作品,请联系作者获取转载授权,否则将追究法律责任
1.C++中的多态
- 多态: 同一个事物在不同场景下的多种形态
2.静态多态
- 函数重载就是一个简单的静态多态,如下面的例子:
// 静态多态
int Add(int a, int b){
return a+b;
}
double Add(double a, int b){
return a+b;
}
int main(){
Add(10, 20);
Add(10.0, 20);
return 0;
}
- 总结:静态多态是编译器在编译期间完成的,编译器会根据实参类型来选择调用合适的函数,如果有合适的函数可以调用就调,没有的话就会发出警告或者报错。
3.动态多态
- 动态多态: 它是在程序运行时根据基类的引用(指针)指向的对象来确定自己具体该调用哪一个类的虚函数,见下面的例子:
// 动态多态
class TakeBus{
public:
void TakeBusToSubway(){
cout << "go to subway\n";
}
void TakeBusToStation(){
cout << "go to station\n";
}
};
class Bus{
public:
virtual void TakeBusToSomewhere(TakeBus& tb) = 0; // 纯虚函数,Bus是个抽象类,提供一个接口
};
class Subway: public Bus{
public:
virtual void TakeBusToSomewhere(TakeBus& tb){ // 虚函数
tb.TakeBusToSubway();
}
};
class Station: public Bus{
public:
virtual void TakeBusToSomewhere(TakeBus& tb){ // 虚函数
tb.TakeBusToStation();
}
};
int main(){
TakeBus tb;
Bus *b = NULL;
for(int i = 1; i <= 10; ++i){
if((rand() % i) & 1)
b = new Subway();
else
b = new Station();
}
b->TakeBusToSomewhere(tb);
delete b;
return 0;
}
- 从上面的例子还发现在每一个函数前都加了virtual这个虚拟关键字,它是在程序运行时根据条件去选择调用哪一个函数,参加下面的例子:
// 动态多态2
// 基类
class Base{
public:
virtual void fun(int i){ // fun在基类中被声明是虚函数,可以动态绑定,根据传入的派生类对象进行调用对应的成员函数
cout << "Base::fun()\n";
}
void fun1(int i){ // fun1在基类中没有被声明是虚函数,不能动态绑定
cout << "Base::fun1()\n";
}
};
class Derived: public Base{
public:
virtual void fun(int i){
cout << "Derived::fun()\n";
}
virtual void fun1(int i){
cout << "Derived::fun1()\n";
}
void fun2(int i){
cout << "Derived::fun2()\n";
}
};
// 全局函数
void TestVirtual(Base& b){
b.fun(0);
b.fun1(1);
}
int main(){
Base b1;
Derived d1;
TestVirtual(b1);
TestVirtual(d1);
return 0;
}
- 动态多态的条件:
- 基类中必须包含虚函数,并且派生类中一定要对基类中的虚函数进行重写
- 通过基类对象的指针或者引用调用虚函数
- 函数重写:
- 基类中将被重写的函数必须为虚函数
- 基类和派生类中虚函数的原型必须保持一致(返回值类型,函数名称以及参数列表),协变[基类(或者派生类)的虚函数返回基类(派生类)的指针(引用)]和析构函数(基类和派生类的析构函数是不一样的)除外
- 访问限定符可以不同
- 哪些函数不能定义为虚函数?
- 友元函数,它不是类的成员函数
- 全局函数
- 静态成员函数,它没有this指针
- 构造函数,拷贝构造函数,以及赋值运算符重载(可以但是一般不建议作为虚函数)
4.抽象类
- 在成员函数(必须为虚函数)的形参列表后面写上=0,则成员函数为纯虚函数。包含纯虚函数的类叫做抽象类(也叫接口类),抽象类不能实例化出对象。纯虚函数在派生类中重新定义以后,派生类才能实例化出对象。纯虚函数是一定要被继承的,否则它存在没有任何意义。
5.参考博客