GEEKBAND C++ 面向?qū)ο蟾呒壘幊?第四周)

C++ 動態(tài)綁定和靜態(tài)綁定


首先明確四個名詞定義:

  • 靜態(tài)類型:對象在聲明時的類型,編譯期就能確定

  • 動態(tài)類型:指針或引用所指的對象的類型

  • 靜態(tài)綁定:綁定的是靜態(tài)類型,依賴于對象的靜態(tài)類型

  • 動態(tài)綁定:綁定的是動態(tài)類型,依賴于對象的動態(tài)類型

類的非虛函數(shù)都是靜態(tài)綁定,虛函數(shù)都是動態(tài)綁定。

下面代碼中,

#include <iostream>

using namespace std;

class Fruit
{
public:
    void print(){cout << "Fruit::print()" << endl;}
    virtual void process(){cout << "Fruit::process()" << endl;}
};
class Apple : public Fruit
{
public:
    void print(){cout << "Apple::print()" << endl;}
    virtual void process(){cout << "Apple::process()" << endl;}
};
class Pear : public Fruit
{
public:
    void print(){cout << "Pear::print()" << endl;}
    virtual void process(){cout << "Pear::process()" << endl;}
};

int main() {
    Pear* pc = new Pear();
    Apple* pb = new Apple();
    Fruit* pa = new Fruit();
    pa = pb;

    pa->print();
    pb->print();
    pc->print();

    pa->process();
    pb->process();
    pc->process();

    return 0;
}

  • pa的靜態(tài)類型是Fruit,動態(tài)類型先是pc指向的Pear,后被改成pb指向的Apple
  • pb的靜態(tài)類型和動態(tài)類型都是Apple
  • pb的靜態(tài)類型和動態(tài)類型都是Pear

代碼執(zhí)行的結(jié)果為:

Fruit::print()
Apple::print()
Pear::print()
Apple::process()
Apple::process()
Pear::process()

可以看到對于類中非虛函數(shù)的調(diào)用,是靜態(tài)類型決定的,在編譯器就能確定;而虛函數(shù)的調(diào)用,是動態(tài)類型決定的,在運行期才能確定。在運行期確定函數(shù)的調(diào)用,就是面向?qū)ο笾兴f的多態(tài)。


注意
《Effective C++》中建議

1.絕對不要重新定義繼承而來的非虛(non-virtual)函數(shù)

2.絕對不要重新定義一個繼承而來的virtual函數(shù)的缺省參數(shù)值,因為缺省參數(shù)值都是靜態(tài)綁定(為了執(zhí)行效率),而virtual函數(shù)卻是動態(tài)綁定。

#include <iostream>

using namespace std;

class Fruit
{
public:
    void print(){cout << "Fruit::print()" << endl;}
    virtual void process(int i = 1){cout << "Fruit::process(), i="<< i << endl;}
};
class Apple : public Fruit
{
public:
    void print(){cout << "Apple::print()" << endl;}
    virtual void process(int i = 10){cout << "Apple::process(), i="<< i << endl;}
};
class Pear : public Fruit
{
public:
    void print(){cout << "Pear::print()" << endl;}
    virtual void process(int i = 20){cout << "Pear::process(), i="<< i << endl;}
};

int main() {
    Pear* pc = new Pear();
    Apple* pb = new Apple();
    Fruit* pa = pc;
    pa = pb;

    pa->print();
    pb->print();
    pc->print();

    pa->process();
    pb->process();
    pc->process();

    return 0;
}
Fruit::print()
Apple::print()
Pear::print()
Apple::process(), i=1
Apple::process(), i=10
Pear::process(), i=20

上面的代碼,pa的process函數(shù)調(diào)用的是子類的process,但是參數(shù)的默認值卻是父類的默認值。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容