溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

C++--同名覆蓋、多態(tài)

發(fā)布時間:2020-07-20 23:31:08 來源:網(wǎng)絡(luò) 閱讀:273 作者:淡淡_小孩 欄目:編程語言

一.同名覆蓋引發(fā)的問題

父子間的賦值兼容--子類對象可以當(dāng)作父類對象使用(兼容性)
1.子類對象可以直接賦值給父類對象
2.子類對象可以直接初始化父類對象
3.父類指針可以指向子類對象
4.父類引用可以直接引用子類對象

代碼示例

#include <iostream>
#include <string>

using namespace std;

class Parent
{
public:
    int mi;

    void add(int i)
    {
        mi += i;
    }

    void add(int a, int b)
    {
        mi += (a + b);
    }
};

class Child : public Parent
{
public:
    int mv;

    void add(int x, int y, int z)
    {
        mv += (x + y + z);
    }
};

int main()
{
    Parent p;
    Child c;

    p = c;

    Parent p1(c);

    Parent& rp = c;
    Parent* pp = &c;

    rp.mi = 100;
    rp.add(5);             
    rp.add(10, 10);        

     pp->mv = 1000;
     pp->add(1, 10, 100);

    return 0;
}

對該代碼進(jìn)行結(jié)果預(yù)測:通過之前的學(xué)習(xí)的同名覆蓋,程序會在 rp.add(5); rp.add(10, 10); 進(jìn)行同名覆蓋,且在父類指針指向子類對象時可以進(jìn)行調(diào)用
運行結(jié)果
C++--同名覆蓋、多態(tài)
通過程序的運行結(jié)果看到,與預(yù)測的結(jié)果不同,這是因為當(dāng)使用父類指針(引用)指向子類對象時
1.子類對象退化為父類對象--所以在pp->mv時會出錯
2.只能訪問父類中定義的成員
3.可以直接訪問被子類覆蓋的同名成員--所以沒發(fā)生同名覆蓋

特殊的同名函數(shù)

1.子類中可以重定義父類中已經(jīng)存在的成員函數(shù)
2.這種重定義發(fā)生在繼承中,叫做函數(shù)重寫
3.函數(shù)重寫是同名覆蓋的一種特殊情況
C++--同名覆蓋、多態(tài)

Q:當(dāng)函數(shù)重寫遇上賦值兼容會發(fā)生什么?
代碼示例

#include <iostream>
#include <string>

using namespace std;

class Parent
{
public:
    int mi;

    void add(int i)
    {
        mi += i;
    }

    void add(int a, int b)
    {
        mi += (a + b);
    }

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

class Child : public Parent
{
public:
    int mv;

    void add(int x, int y, int z)
    {
        mv += (x + y + z);
    }

    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);    
    how_to_print(&c);    

    return 0;
}

輸出結(jié)果
C++--同名覆蓋、多態(tài)
問題分析
1.編譯期間,編譯器只能根據(jù)指針的類型判斷所指向的對象
2.根據(jù)賦值兼容,編譯器認(rèn)為父類指針指向的是父類對象
3.因此,編譯結(jié)果只可能是調(diào)用父類中定義的同名函數(shù)
C++--同名覆蓋、多態(tài)
在編譯這個函數(shù)的時候,編譯器不可能知道指針p指向了什么,但是編譯器沒有理由報錯。于是,編譯器認(rèn)為最安全的做法時調(diào)用父類的print函數(shù),因為父類和子類肯定都有相同的print函數(shù)

二.多態(tài)的概念和意義

函數(shù)重寫
1.父類中被重寫的函數(shù)依然會繼承給子類
2.子類中重寫的函數(shù)將覆蓋父類中的函數(shù)
3.通過作用域分辨符(::)可以訪問父類中的函數(shù)

A.面向?qū)ο笾衅诖男袨?/strong>
1.根據(jù)實際的對象類型判斷如何調(diào)用重寫函數(shù)
2.父類指針指向--a.父類對象調(diào)用父類中定義的函數(shù)b.子類對象則調(diào)用子類中定義的函數(shù)
B.面向?qū)ο蟮亩鄳B(tài)的概念
1.根據(jù)實際的對象類型決定函數(shù)調(diào)用的具體目標(biāo)
2.同樣的調(diào)用語句在實際運行時有多種不同的表現(xiàn)形態(tài)
C++--同名覆蓋、多態(tài)
C.C++語言中直接支持多態(tài)的概念
1.通過使用virtual關(guān)鍵字對多態(tài)進(jìn)行支持
2.被virtual聲明的函數(shù)被重寫后具有多態(tài)特性
3.被virtual聲明的函數(shù)叫做虛函數(shù)

#include <iostream>
#include <string>

using namespace std;

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

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

void how_to_print(Parent* p)
{
    p->print();     // 展現(xiàn)多態(tài)的行為
}

int main()
{
    Parent p;
    Child c;

    how_to_print(&p);    
    how_to_print(&c);    

    return 0;
}

運行結(jié)果
C++--同名覆蓋、多態(tài)
D.多態(tài)的意義
1.在程序的運行過程中展現(xiàn)出多態(tài)的特性
2.函數(shù)重寫必須實現(xiàn)多態(tài),否則沒有意義
3.多態(tài)時面向?qū)ο蠼M件化程序設(shè)計的基礎(chǔ)特性

靜態(tài)聯(lián)編--在程序的編譯期間就能確定具體的函數(shù)調(diào)用
動態(tài)聯(lián)編--在程序?qū)嶋H運行后才能確定具體的函數(shù)調(diào)用

#include <iostream>
#include <string>

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);     // 展現(xiàn)多態(tài)的特性
                       // 動態(tài)聯(lián)編
}

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;
}

運行結(jié)果
C++--同名覆蓋、多態(tài)
小結(jié)
1.函數(shù)重寫只可能發(fā)生在父類與子類之間
2.根據(jù)實際對象的類型確定調(diào)用的具體函數(shù)
3.virtual關(guān)鍵字是C++中支持多態(tài)的唯一方式
4.被重寫的虛函數(shù)表現(xiàn)出多態(tài)的特性

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI