什麼多態還不懂, 趕快看這裏。


在這裏插入圖片描述

1、概念

多態是c++的特徵之一
多態的分類:靜態多態(靜態聯編)、動態多態(動態聯編)
靜態多態(靜態聯編):函數入口地址 是在 編譯階段 確定(運算符重載、函數重載)
動態多態(動態聯編):函數入口地址 是在 運行階段 確定(虛函數)

2、引入

class Animal
{
public:
    void sleep(void)
    {
        cout<<"animal 動物在睡覺"<<endl;
    }
};

class Cat:public Animal
{
public:
    void sleep(void)
    {
        cout<<"Cat 貓在睡覺!! 喵喵"<<endl;
    }
};
void test01()
{
    //用基類(指針或引用) 保存 子類對象(向上轉換)
    Animal *p = new Cat;
    p->sleep();//調用的是基類的sleep

    Cat cat;
    Animal &ob = cat;
    ob.sleep();//調用的是基類的sleep
    //怎麼調用子類的sleep呢?
}

在這裏插入圖片描述
運行結果:
在這裏插入圖片描述

總結:基類指針、引用 只能訪問 子類對象中 基類部分 數據

3、使用基類指針、引用 訪問 子類對象中的成員方法(虛函數)

使用virtual修飾成員函數 該成員函數就是虛函數。

class Animal
{
public:
    //虛函數 
    virtual void sleep(void)
    {
        cout<<"animal 動物在睡覺"<<endl;
    }
};

在這裏插入圖片描述
vfptr虛函數指針 指向的是虛函數表(vftable)
vftable表存放的是 vfptr做保存的函數入口地址
注意://如果 Animal沒有涉及到繼承 函數指針變量 就指向自身sleep

class Animal
{
public:
    //虛函數 本質 是一個函數指針變量
    virtual void sleep(void)
    {
        cout<<"animal 動物在睡覺"<<endl;
    }
};
void test01()
{
    //如果 Animal沒有涉及到繼承  函數指針變量 就指向自身sleep
    Animal ob;
    ob.sleep();
}

運行結果:
在這裏插入圖片描述

4、擁有虛函數的類 涉及得到繼承

class Animal
{
public:
    //虛函數 本質 是一個函數指針變量
    virtual void sleep(void)
    {
        cout<<"animal 動物在睡覺"<<endl;
    }
};
class Cat:public Animal
{
public:
    virtual void sleep(void)
    {
        cout<<"貓在睡覺!!喵喵"<<endl;
    }
};

在這裏插入圖片描述
在這裏插入圖片描述

void test01()
{
    Animal *p = new Cat;
    p->sleep();//調用的是cat中sleep
}

運行結果:
在這裏插入圖片描述

總結:

當虛函數涉及到繼承的時候 子類 會繼承 父類的(虛函數指針vfptr 虛函數表vftable),編譯器會將虛函數表中的函數入口地址 更新 成子類的 同名(返回值、參數都相同)的函數入口地址。
如果基類指針、引用 訪問虛函數的時候 就會 間接的調用 子類的虛函數.

5、虛函數的應用案例(基類指針、引用 作爲函數的參數)

在這裏插入圖片描述

#include <iostream>

using namespace std;
class Base
{
public:
    virtual void sleep(void)
    {
        cout<<"父親在睡覺"<<endl;
    }
};

class Son1:public Base
{
public:
    void sleep(void)
    {
        cout<<"Son1在安靜的睡覺"<<endl;
    }
};
class Son2:public Base
{
public:
    virtual void sleep(void)
    {
        cout<<"Son2在輕度的睡覺"<<endl;
    }
};
class Son3:public Base
{
public:
    virtual void sleep(void)
    {
        cout<<"Son3在雨聲般的睡覺"<<endl;
    }
};
class Son4:public Base
{
public:
    virtual void sleep(void)
    {
        cout<<"Son4在鼾聲如雷"<<endl;
    }
};

//以基類指針作爲函數的參數 函數可以操作該基類派生出的任意子類對象
void sleepFun(Base &ob)
{
    ob.sleep();
}

int main(int argc, char *argv[])
{
    Son1 ob1;
    Son2 ob2;
    Son3 ob3;
    Son4 ob4;
    sleepFun(ob1);
    sleepFun(ob2);
    sleepFun(ob3);
    sleepFun(ob4);
    return 0;
}

#千鋒教育#
人活着就要快樂。
運行結果:
在這裏插入圖片描述

多態涉及到 易考的面試題:

問題:C++的動態捆綁機制是怎麼樣的?
首先,我們看看編譯器如何處理虛函數。當編譯器發現我們的類中有虛函數的時候,編譯器會創建一張虛函數表,把虛函數的函數入口地址放到虛函數表中,並且在類中祕密增加一個指針,這個指針就是vpointer(縮寫vptr),這個指針是指向對象的虛函數表。在多態調用的時候,根據vptr指針,找到虛函數表來實現動態綁定。

各位看官,感覺我寫的怎麼樣呢, 大家有沒有看懂呢, 歡迎評論
如果對大家有幫助,不要忘記點個贊哦.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章