国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > C++ > 正文

C++中的虛函數(shù)重載

2019-11-08 02:31:10
字體:
供稿:網(wǎng)友

在一次修改代碼過程中踩的坑,下來研究了一下,發(fā)現(xiàn)C++中虛函數(shù)重載后會(huì)產(chǎn)生很多有意思的情況,在這里總結(jié)了一下。

C++中有重載(overload)和重寫(override)以及重定義這幾個(gè)概念,1 overload:指的是相同作用域中的兩個(gè)函數(shù)的函數(shù)名相同,但參數(shù)列表的個(gè)數(shù)、順序、類型不同。而override指的是子類中重新定義的父類的虛函數(shù)。2 override:overload要求兩個(gè)函數(shù)的參數(shù)列表必須不同,但是不要求這兩個(gè)函數(shù)必須是虛函數(shù)。而override要求必須是虛函數(shù)且父類的虛函數(shù)必須有virtual關(guān)鍵字,函數(shù)的參數(shù)列表和返回值也必須相同。子類中override的虛函數(shù)的訪問修飾符可以不同。3 重定義也是描述分別位于父類與子類中的同名函數(shù)的,但返回值可以不同。如果參數(shù)列表不同,這時(shí)子類中重定義的函數(shù)不論是否有virtual關(guān)鍵字,都會(huì)隱藏父類的同名函數(shù)。如果參數(shù)列表相同,但父類中的同名函數(shù)沒有virtual關(guān)鍵字修飾,此時(shí)父類中的函數(shù)仍然被隱藏。

虛函數(shù)的典型用法是:

#include <iostream>using namespace std; class Base{public:    virtual void f();};void Base::f(){    cout << "Base::f()" << endl;}class Derived:public Base{public:    virtual void f();};void Derived::f(){    cout << "Derived::f()" << endl;}int main() {    Base *p1 = new Base;    Base *p2 = new Derived;    p1->f();    p2->f();        delete p1;    delete p2;    return 0;}

程序的輸出是:

Base::f()Derived::f()

那么如果虛函數(shù)之間又發(fā)生了overload,會(huì)出現(xiàn)什么情況?我們先看最簡單的情況:

#include <iostream>using namespace std; class Base{public:    virtual void f(int);};void Base::f(int a){    cout << "Base::f(int) " << a << endl;}class Derived:public Base{public:    virtual void f();};void Derived::f(){    cout << "Derived::f()" << endl;}int main() {    Base *p1 = new Base;    p1->f(1);        Base *p2 = new Derived;    p2->f();        delete p1;    delete p2;        return 0;}

編譯上面的代碼,會(huì)發(fā)生如下錯(cuò)誤:

test.cpp: In function ‘int main()’:test.cpp:28:11: error: no matching function for call to ‘Base::f()’     p2->f();           ^test.cpp:10:6: note: candidate: virtual void Base::f(int) void Base::f(int a){      ^test.cpp:10:6: note:   candidate expects 1 argument, 0 PRovided

這就是因?yàn)楦割愔刑摵瘮?shù)的參數(shù)列表已經(jīng)發(fā)生變化,這時(shí)不論子類中重定義的函數(shù)不論是否有virtual關(guān)鍵字,都會(huì)隱藏父類的同名函數(shù)。這時(shí)子類中只是重定義了一個(gè)自己的函數(shù)virtual void f(),而并沒有override父類中對(duì)應(yīng)的虛函數(shù)。p2是一個(gè)指向Base類型的指針,根據(jù)虛函數(shù)的特性,對(duì)p2→f();的處理取決于是否override了父類的虛函數(shù),如果沒有,仍然會(huì)調(diào)用調(diào)用父類中被override的虛函數(shù),但是現(xiàn)在父類中的函數(shù)已經(jīng)成為了virtual void f(int),因此在執(zhí)行p2→f()時(shí)會(huì)由于缺少輸入?yún)?shù)而出現(xiàn)上述錯(cuò)誤。為了證明上述論斷,可以在執(zhí)行p2→f()時(shí)傳入?yún)?shù)來判斷:

#include <iostream>using namespace std; class Base{public:    virtual void f(int);};void Base::f(int a){    cout << "Base::f(int) " << a << endl;}class Derived:public Base{public:    virtual void f();};void Derived::f(){    cout << "Derived::f()" << endl;}int main() {    Base *p1 = new Base;    p1->f(1);        Base *p2 = new Derived;    p2->f(2);        delete p1;    delete p2;        return 0;}

這時(shí)可以通過編譯,執(zhí)行結(jié)果為

Base::f(int) 1Base::f(int) 2

可以看到,子類自己定義的virtual void f()其實(shí)是父類的virtual void f(int)的一個(gè)重定義的函數(shù),這時(shí)盡管p2實(shí)際指向了一個(gè)Derived對(duì)象,但由于沒有override父類對(duì)應(yīng)的虛函數(shù),在執(zhí)行 p2→f(2)時(shí)將執(zhí)行父類的virtual void f(int)。也可以這樣修改:

#include <iostream>using namespace std; class Base{public:    virtual void f(int);    virtual void f();};void Base::f(int a){    cout << "Base::f(int) " << a << endl;}void Base::f(){    cout << "Base::f() " << endl;}class Derived:public Base{public:    virtual void f();};void Derived::f(){    cout << "Derived::f()" << endl;}int main() {    Base *p1 = new Base;    p1->f(1);        Base *p2 = new Derived;    p2->f();        delete p1;    delete p2;        return 0;}

因?yàn)楦割愔卸x了可被子類override的函數(shù),所以這時(shí)執(zhí)行p2→f()又會(huì)重新執(zhí)行子類的virtual void f():

Base::f(int) 1Derived::f()

我們甚至還可以這樣驗(yàn)證:

#include <iostream>using namespace std; class Base {public:    virtual void f(int);    virtual void f();};void Base::f(int a) {    cout << "Base::f(int) " << a << endl;}void Base::f() {    cout << "Base::f() " << endl;}class Derived:public Base {public:    virtual void f(float);};void Derived::f(float a) {    cout << "Derived::f(float)" << showpoint << a << endl;}int main() {    Base *p1 = new Base;    p1->f(1);        Base *p2 = new Derived;    p2->f(**2.0**);        delete p1;    delete p2;        return 0;}

這時(shí)輸出仍然為

Base::f(int) 1Base::f(int) 2

這說明如果通過指向父類的指針,調(diào)用虛函數(shù)時(shí),如果子類重定義了該虛函數(shù)(參數(shù)列表發(fā)生變化),則實(shí)際調(diào)用的仍是父類中的虛函數(shù)。上面都是通過指向父類的指針來調(diào)用虛函數(shù)的,那么如果通過指向子類的指針調(diào)用虛函數(shù)會(huì)發(fā)生什么:

#include <iostream>using namespace std; class Base {public:    virtual void f(int);    virtual void f();};void Base::f(int a) {    cout << "Base::f(int) " << a << endl;}void Base::f() {    cout << "Base::f() " << endl;}class Derived:public Base {public:    virtual void f(float);};void Derived::f(float a) {    cout << "Derived::f(float)" << showpoint << a << endl;}int main() {    Base *p1 = new Base;    p1->f(1);        Derived *p2 = new Derived;    p2->f(2.0);    p2->f(3);        delete p1;    delete p2;        return 0;}

這時(shí)輸出就變?yōu)榱耍?/p>

Base::f(int) 1Derived::f(float)2.00000Derived::f(float)3.00000

這說明,如果通過指向子類的指針調(diào)用虛函數(shù),并且子類重定義了父類的虛函數(shù),這時(shí)實(shí)際調(diào)用的就將是子類中的虛函數(shù)。


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表

圖片精選

主站蜘蛛池模板: 锡林郭勒盟| 雷波县| 松阳县| 当涂县| 仁怀市| 江北区| 高州市| 凤山市| 高碑店市| 阜康市| 新宾| 玉田县| 平凉市| 化州市| 清丰县| 上高县| 齐齐哈尔市| 手游| 昌都县| 寿光市| 枣强县| 内江市| 屯留县| 仲巴县| 布尔津县| 珲春市| 大渡口区| 通辽市| 阳泉市| 辽阳县| 浮山县| 谢通门县| 甘孜县| 嘉祥县| 乳源| 枣庄市| 静宁县| 娱乐| 东乡族自治县| 南华县| 泽库县|