C++中的多态(一)

来源:互联网 发布:免费听小说的软件 编辑:程序博客网 时间:2024/05/22 10:43

多态:一词最初来源于希腊语,意思是具有多种形式或形态的情形。通俗的讲,水在不同的温度下所呈现的不同的状态,比如:水在零摄氏度以下是固态的,在0~100度之间是液态的,在100度以上是气态的。

在C++语言中多态有着更广泛的含义

这里写图片描述

【静态多态】:

int Add(int a, int b){    return a + b;}float Add(float a, float b){    return a + b;}int main(){    cout << Add(30, 20) << endl;    cout << Add(11.10f, 22.20f) << endl;    return 0;}

运行结果:
这里写图片描述

静态多态:编译器在编译期间完成的,编译器根据函数实参的类型(可能会进行隐式类型转换),可推断出要调用那个函数,如果有对应的函数就调用该函数,否则出现编译错误。

【动态多态】:

动态绑定:在程序执行期间(非编译期)判断所引用对象的实际类型,根据其实际类型调用相应的方法。
使用virtual关键字修饰类的成员函数时,指明该函数为虚函数,派生类需要重新实现,编译器将实现动态绑定。

下来咱们举一个简单的例子:

class WashRoom//修建厕所{public:    void GoToManWashRoom()    {        cout << "Man-->Please Left" << endl;    }    void GoToWomanWashRoom()    {        cout << "Woman-->Please Right" << endl;    }};class Person//人{public:    virtual void GoToWashRoom(WashRoom & _washRoom) = 0;};class Man :public Person//男士往左{public:    virtual void GoToWashRoom(WashRoom & washRoom)    {        washRoom.GoToManWashRoom();    }};class Woman :public Person//女士朝右{public:    virtual void GoToWashRoom(WashRoom & washRoom)    {        washRoom.GoToWomanWashRoom();    }};void FunTest(){    WashRoom washRoom;//找到厕所    //来了十个人,性别随机    for (int iIdx = 1; iIdx <= 10; ++iIdx)    {        Person* pPerson;//一个人        int iPerson = rand() % iIdx;//性别随机        if (iPerson & 0x01)            pPerson = new Man;//若为男士        else            pPerson = new Woman; //若为女士            pPerson->GoToWashRoom(washRoom);//选择适当方向        delete pPerson;//销毁对象        pPerson = NULL;        Sleep(1000);    }}int main(){    FunTest();    return 0;}

运行结果:
这里写图片描述

【动态绑定条件】
1、通过基类类型的引用或者指针调用虚函数
这里写图片描述

这里写图片描述

2、必须是虚函数(派生类一定要重写基类的虚函数)

class Base{public:    virtual void FunTest1(int _iTest)    {         cout << "Base::FunTest1()" << endl;     }    void FunTest2(int _iTest)    {         cout << "Base::FunTest2()" << endl;     }    virtual void FunTest3(int _iTest1)    {         cout << "Base::FunTest3()" << endl;    }    virtual void FunTest4(int _iTest)    {         cout << "Base::FunTest4()" << endl;     }};class Derived :public Base{public:    virtual void FunTest1(int _iTest)    {        cout << "Derived::FunTest1()" << endl;    }    virtual void FunTest2(int _iTest)    {        cout << "Derived::FunTest2()" << endl;     }    void FunTest3(int _iTest1)    {         cout << "Derived::FunTest3()" << endl;    }    virtual void FunTest4(int _iTest1, int _iTest2)    {        cout << "Derived::FunTest4()" << endl;    }};int main(){    Base* pBase = new Derived;    pBase->FunTest1(0);    pBase->FunTest2(0);    pBase->FunTest3(0);    pBase->FunTest4(0);    pBase->FunTest4(0);    return 0;}

运行结果:
这里写图片描述

继承体系同名成员函数的关系:
这里写图片描述

那些成员函数不能定义成虚函数?

(1).友元函数
(2).构造函数
(3).静态成员函数(static)
(4).内联函数(inline)

注:
(1)最好将基类中的析构函数给成virtual;
(2)最好不要使基类的运算符重载给成virtual

总结:
1、派生类重写基类的虚函数实现多态,要求函数名、参数列表、返回值完全相同(协变除外)。
2、基类中定义了虚函数,在派生类中该函数始终保持虚函数的特性。
3、只有类的非静态成员函数才能定义为虚函数,静态成员函数不能定义为虚函数。
4、如果在类外定义虚函数,只能在声明函数时加virtual关键字,定义时不用加。
5、构造函数不能定义为虚函数,虽然可以将operator=定义为虚函数,但最好不要这么做,使用时容易混淆。
6、不要在构造函数和析构函数中调用虚函数,在构造函数和析构函数中,对象是不完整的,可能会出现未定义的行为。
7、最好将基类的析构函数声明为虚函数。(析构函数比较特殊,因为派生类的析构函数跟基类的析构函数名称不一样,但是构成覆盖,这里编译器做了特殊处理)
8、虚表是所有类对象实例共用的

原创粉丝点击