多态总结

一、什么是多态?

多态就是具有多种形式或形态的情形。在我C++中就是有几个相似却不完全相同的对象,对这些对象发出同一消息时,这些对象分别执行不同的操作,完成不同的功能。

二、多态的分类

    wKioL1cTE3CBl5sUAABCadaPpd8883.png

 

三、静态多态

 1.函数重载

(1)定义

 函数重载是指在同一作用域内,可以有一组具有相同函数名不同参数列表的函数,这组函数被称为重载函数。

(2)注意

 重载函数的参数个数参数类型参数顺序三者中必须至少有一个不同。函数返回值可以相同也可以不同。

(3)程序实例

#include<iostream>

using namespace std;

int Add(int left, int right)

{

return left + right;

}

 

float Add(float left, float right)

{

return left + right;

}

int main()

{

cout << Add(10, 20) << endl;

cout << Add(12.34f, 56.78f) << endl;

system("pause");

return 0;

}

通过实例可以发现,函数重载是怎么调用对应函数的呢!通过函数调用,获取函数名,找到同名函数,然后获得函数各参数表达式类型,同时与实参比较是否匹配,如果匹配则调用该函数,如果没有匹配类型则报错。

四、动态多态

 1.虚函数

 (1)定义

  使用virtual关键字修饰的函数称为虚函数。

(2)注意

  一个类函数的调用并不是在编译时刻被确定,而是在运行时刻被确定。

(3)程序实例

#include<iostream>

using namespace std;

 

class CBase

{

public:

virtual void FunTest1(int _iTest)

{

cout << "CBase::FunTest1()" << endl;

}

void FunTest2(int _iTest)

{

cout << "CBase::FunTest2()" << endl;

}

virtual void FunTest3(int _iTest1)

{

cout << "CBase::FunTest3()" << endl;

}

virtual void FunTest4(int _iTest)

{

cout << "CBase::FunTest4()" << endl;

}

};

 

class CDerived :public CBase

{

public:

virtual void FunTest1(int _iTest)

{

cout << "CDerived::FunTest1()" << endl;

}

virtual void FunTest2(int _iTest)

{

cout << "CDerived::FunTest2()" << endl;

}

void FunTest3(int _iTest1)

{

cout << "CDerived::FunTest3()" << endl;

}

virtual void FunTest4(int _iTest1, int _iTest2)

{

cout << "CDerived::FunTest4()" << endl;

}

};

 

int main()

{

CBase* pBase = new CDerived;

pBase->FunTest1(0);

pBase->FunTest2(0);

pBase->FunTest3(0);

pBase->FunTest4(0);

CDerived d;

d.FunTest4(0, 0);

d.CBase::FunTest4(0);

system("pause");

return 0;

}

wKioL1cTE73g3jxWAAAhXCXFPvc814.png

(4)总结

1.派生类重写基类的虚函数实现多态,要求函数名、参数列表、返回值完全相同。(协变除外)

2、基类中定义了虚函数,在派生类中该函数始终保持虚函数的特性。

3、只有类的成员函数才定义为虚函数,静态成员函数不能定义为虚函数。

4、如果在类外定义虚函数,只能在声明函数时加virtual关键字,定义时不用加。

5、构造函数不能定义为虚函数,虽然可以将operator=定义为虚函数,但最好不要这么做,使用时容易混淆。

6、不要在构造函数和析构函数中调用虚函数,在构造函数和析构函数中,对象是不完整的,可能会出现未定义的行为。

7、最好将基类的析构函数声明为虚函数。(析构函数比较特殊,因为派生类的析构函数跟基类的析构函数名称不一样,但是构成覆盖,这里编译器做了特殊处理)

8、虚表是所有类对象实例共用的。