【C++】 49_多態的概念和意義

函數重寫回顧

  • 父類中被重寫的函數依然會繼承給子類
  • 子類中重寫的函數將覆蓋父類中的函數
  • 經過做用域分辨符 (::) 能夠訪問到父類中的函數
void code()
{
    Child c;
    Parent* p = &c;
    
    c.Parent::print();    // 從父類中繼承
    c.print();            // 從子類中重寫
    
    p->print();           // 從父類中定義
}

思考:
爲何要重寫父類中的成員函數呢?ios

答:
父類中提供的成員函數版本不能知足需求編程

多態的概念和意義

  • 面向對象中指望的行爲函數

    • 根據實際的對象類型判斷如何調用重寫函數
  • 父類指針( 引用 )指向組件化

    • 父類對象則調用父類中定義的函數
    • 子類對象則調用子類中定義的函數

  • 面向對象中多態的概念spa

    • 根據實際的對象類型決定函數調用的具體目標
    • 一樣的調用語句在實際運行時有多種不一樣的表現形態

clipboard.png

  • C++ 語言直接支持多態的概念設計

    • 經過 virtual 關鍵字對多態進行支持
    • 被 virtual 聲明的函數被重寫後具備多態性
    • 被 virtual 聲明的函數叫作虛函數

編程實驗: 多態初體驗

#include <iostream>

using namespace std;

class Parent
{
public:
    virtual void print()
    {
        cout << "I'm Parent." << endl;
    }
};

class Child : public Parent
{
public:
    void print()          // 由於繼承, 子類中 void print() 也是虛函數
    {
        cout << "I'm Child." << endl;
    }
};

void how_to_print(Parent* p)
{
    p->print();          // 展示多態的行爲
}

int main()
{
    Parent p;
    Child  c;
    
    how_to_print(&p);    // Expected to print: I'm Parent 
    how_to_print(&c);    // Expected to print: I'm Child 
    
    return 0;
}
輸出:
I'm Parent.
I'm Child.
  • 多態的意義3d

    • 在程序運行過程當中展示出動態的特性
    • 函數重寫必須多態實現,不然沒有意義
    • 多態是面向對象組件化程序設計的基礎特性

  • 理論中的概念指針

    • 靜態聯編code

      • 在程序的編譯期間就能肯定具體的函數調用對象

        • 如: 函數重載
    • 動態聯編

      • 在程序實際運行後才能肯定具體的函數調用

        • 如: 函數函數重寫

實例分析: 動態聯編與靜態聯編

#include <iostream>

using namespace std;

class Parent
{
public:
    virtual void func()
    {
        cout << "void func()" << endl;
    }
    virtual void func(int i)
    {
        cout << "void func(int i) : " << i << endl;
    }
    virtual void func(int i, int j)
    {
        cout << "void func(int i, int j)" << "(" << i << ", " << j << ")" << endl;
    }
};

class Child : public Parent
{
public:
    void func(int i, int j)
    {
        cout << "void func(int i, int j) : " << i + j << endl;
    }

    void func(int i, int j, int k)
    {
        cout << "void func(int i, int j, int k) : " << i + j + k << endl;
    }
};

void run(Parent* p)
{
    p->func(1, 2);          // 展示多態的行爲
                            // 動態聯編
}                    

int main()
{
    Parent p;
    
    p.func();                // 靜態聯編
    p.func(1);               // 靜態聯編
    p.func(1, 2);            // 靜態聯編
    
    cout << endl;
    
    Child c;
    
    c.func(1, 2);             // 靜態聯編
    
    cout << endl;
    
    run(&p);
    run(&c);
    
    return 0;
}
輸出:
void func()
void func(int i) : 1
void func(int i, int j)(1, 2)

void func(int i, int j) : 3

void func(int i, int j)(1, 2)
void func(int i, int j) : 3

編程實驗: 江湖恩怨

#include <iostream>
#include <string>

using namespace std;

class Boss
{
public:
    int fight()
    {
        int ret = 10;
        
        cout << "Boss::fight() : " << ret << endl;
        
        return ret;
    }
};

class Master
{
public:
    virtual int eightSwordKill()
    {
        int ret = 8;
        
        cout << "Master::eightSwordKill() : " << ret << endl;
        
        return ret;
    }
};

class NewMaster : public Master
{
public:
    int eightSwordKill()
    {
        int ret = Master::eightSwordKill() * 2;
        
        cout << "Master::eightSwordKill() : " << ret << endl;
        
        return ret;
    } 
};

void field_pk(Master* master, Boss* boss)
{
    int k = master->eightSwordKill();
    int b = boss->fight();
    
    if( k < b )
    {
        cout << "Master is killed... " << endl;
    }
    else
    {
        cout << "Boss is killed... " << endl;
    }
}

int main()
{
    Master master;
    Boss boss;
    
    cout << "Master vs Boss" << endl;
    
    field_pk(&master, &boss);
    
    cout << "NewMaster vs Boss" << endl;
    
    NewMaster newMaster;
    
    field_pk(&newMaster, &boss);

    return 0;
}
輸出:
aster vs Boss
Master::eightSwordKill() : 8
Boss::fight() : 10
Master is killed...
NewMaster vs Boss
Master::eightSwordKill() : 8
NewMaster::eightSwordKill() : 16
Boss::fight() : 10
Boss is killed...

小結

  • 函數重寫只可能發生在父類與子類之間
  • 根據實際對象的類型肯定調用的具體函數
  • virtual 關鍵字是 C++ 中支持多態的惟一方式
  • 被重寫的虛函數可表現出多態的特性

以上內容參考狄泰軟件學院系列課程,請你們保護原創!

相關文章
相關標籤/搜索