在线不卡日本ⅴ一区v二区_精品一区二区中文字幕_天堂v在线视频_亚洲五月天婷婷中文网站

  • <menu id="lky3g"></menu>
  • <style id="lky3g"></style>
    <pre id="lky3g"><tt id="lky3g"></tt></pre>

    C++之對(duì)待繼承得到的名字

    一.結(jié)論

    • 派生類中變量或者函數(shù)名字覆蓋基類的名字,是公有繼承所不希望的
    • 使用using聲明或者轉(zhuǎn)調(diào)函數(shù)可以使隱藏的函數(shù)名字或者變量名字可見(jiàn)

    二.詳細(xì)說(shuō)明

    為了說(shuō)明以上的結(jié)論,首先需要說(shuō)明隱藏、覆蓋以及作用域等概念,接著舉例說(shuō)明隱藏、覆蓋以及作用域等帶來(lái)的問(wèn)題,最后以解決方法解決以上問(wèn)題。

    2.1 隱藏、覆蓋和作用域

    作用域:從字面上理解,某事物起作用的地方,比如說(shuō)白天太陽(yáng)能夠照射的地方,能看到太陽(yáng),而照不到的地方就看不到太陽(yáng),能夠看到太陽(yáng)的地方就是太陽(yáng)的作用域。比較官方的定義如下:

    作用域:程序設(shè)計(jì)概念,通常來(lái)說(shuō),一段程序代碼中所用到的名字并不總是有效/可用的,而限定這個(gè)名字的可用性的代碼范圍就是這個(gè)名字的作用域 —百度百科

    隱藏:從字面上理解就是,因?yàn)槟呈挛锏牡絹?lái),一些事物被隱藏起來(lái)了,但是可以通過(guò)一些辦法讓它顯現(xiàn)出來(lái),比如還以上面的例子,太陽(yáng)照射不到的地方通過(guò)鏡子將陽(yáng)關(guān)反射到被隱藏事物的地方(轉(zhuǎn)調(diào)),隱藏的事物亦可以看到太陽(yáng)了。官方的定義:

    派生類將繼承的基類的同名的成員變量和成員方法隱藏起來(lái),通過(guò)派生類只能訪問(wèn)到自己的成員變量和成員方法。

    覆蓋: 從字面上理解,某些事物因?yàn)橛袥_突,在一些作用域下不能同時(shí)出現(xiàn),在某一片陽(yáng)光下,要么只能出現(xiàn)事物A,要么只能出現(xiàn)事物B。

    覆蓋往往與繼承的類中有virtual修飾的函數(shù)有關(guān)。virtual修飾的函數(shù)為虛函數(shù)。而覆蓋就是基類中有virtual修飾的函數(shù),且在派生類中有與基類中的虛函數(shù)同名且同參數(shù)列表的函數(shù),那么派生類中的的該函數(shù)就會(huì)將基類中的函數(shù)覆蓋,調(diào)用時(shí)無(wú)法調(diào)用基類中的函數(shù)

    2.2.局部變量和全局變量選擇

    int val = 1; // global valuevoid main(){ double val = 2.5; // local value std::cout << val << std::endl; // out 2.5 std::cout << ::val << std::endl; // out 1}

    運(yùn)行結(jié)果:

    2.51

    當(dāng)編譯器在cout處輸出val時(shí),將首先查找 TestFun 的作用域中是否有名字 val ,如果有則它將直接輸出這個(gè)變量的值,如果沒(méi)有則會(huì)向TestFun之外的地方查找val符號(hào),找到則直接輸出。此處輸出2.5,局部的val變量覆蓋了全局的val變量。如果要想使用全局變量val,需要添加作用域::val。

    此處局部變量掩蓋全局變量,若想使用全局變量可添加作用域的形式使用

    2.3. 繼承時(shí)變量選擇

    有如下類繼承關(guān)系,基類中包含純虛函數(shù)、虛函數(shù)和非虛函數(shù),派生類公有繼承基類,包含基類中非虛函數(shù)的同名同參函數(shù)和獨(dú)有函數(shù),如下:

    class Base {private: int val; public: virtual void mFun1() = 0; virtual void mFun1(double) { std::cout << "Base mFun1 with param double" << std::endl; } virtual void mFun2() { std::cout << "Base mFun2" << std::endl; } void mFun3() { std::cout << "Base mFun3" << std::endl; } void mFun3(float) { std::cout << "Base mFun3 with param float" << std::endl; }};class Derived: public Base {public: virtual void mFun1() { std::cout << "Derieved mFun1" << std::endl; } void mFun3() { std::cout << "Derieved mFun3" << std::endl; mFun2(); } void mFun4() { std::cout << "Derieved mFun4" << std::endl; mFun3(); // mFun3(1.25); // no matching function }};

    1.在構(gòu)建派生類實(shí)例時(shí),調(diào)用同名同參的非虛函數(shù)mFun3時(shí),其搜索路徑是,先搜索mFun3內(nèi)部是否找到mFun2,如果沒(méi)有找到則在類Derived中查找mFun2,如果類內(nèi)有找到則繼續(xù)向上Base類中查找mFun2,如果沒(méi)有找到則繼續(xù)向本文件中查找mFun2等等。此處mFun2在Base類中找到,如下例子:

    int main() { Derived der; der.mFun3(); return 0;}

    運(yùn)行結(jié)果:

    Derieved mFun3Base mFun2

    2.在構(gòu)建派生類實(shí)例時(shí),調(diào)用函數(shù)mFun4時(shí),mFun4中現(xiàn)調(diào)用的mFun3只會(huì)調(diào)用派生類Derived中的mFun3,且無(wú)法調(diào)用帶參數(shù)的mFun3,否則編譯時(shí)會(huì)報(bào)no matching function錯(cuò)誤,實(shí)例中調(diào)用帶參的mFun3一樣報(bào)錯(cuò),因?yàn)榕缮愔械暮瘮?shù)覆蓋了基類中的同名函數(shù)包括不同參數(shù),換句話說(shuō)派生類中的同名函數(shù)覆蓋了了Base::mFun1和Base::mFun3。 如下例子:

    int main() { Derived der; der.mFun1(); // call Derived mFun1 der.mFun4(); // call Derived mFun4 // der.mFun3(1.25); // no matching function return 0;}

    運(yùn)行結(jié)果

    Derieved mFun4Derieved mFun3Base mFun2

    從上面的兩個(gè)例子中可以發(fā)現(xiàn)一個(gè)很明顯的問(wèn)題,由于同名覆蓋的情況,導(dǎo)致在派生類中無(wú)法調(diào)用基類中同名不同參數(shù)的函數(shù), 以下就是一些解決辦法

    2.4 使用using聲明

    使用using 聲明可以將作用域從原先限定的地方拓展到聲明的地方,增加其使用范圍,例子如下:

    // Base基類同上class Derived: public Base {public: using Base::mFun3; virtual void mFun1() { std::cout << "Derieved mFun1" << std::endl; } void mFun3() { std::cout << "Derieved mFun3" << std::endl; mFun2(); } void mFun4() { std::cout << "Derieved mFun4" << std::endl; mFun3(); // mFun3(1.25); // no matching function }};

    使用Demo進(jìn)行測(cè)試:

    int main() { Derived der; der.mFun1(); // call Derived mFun1 der.mFun1(1.0); // call Base mFun1 der.mFun4(); // call Derived mFun4 der.mFun3(); // call Derived mFun3 der.mFun3(1.25); // call Base mFun3 return 0;}

    運(yùn)行結(jié)果:

    Derieved mFun1 // der.mFun1();Base mFun1 with param double // der.mFun1(1.0);Derieved mFun4 // der.mFun4();Derieved mFun3Base mFun2Derieved mFun3 // der.mFun3();Base mFun2Base mFun3 with param float // der.mFun3(1.25);

    從結(jié)果中可以看出使用using聲明將基類中的函數(shù)作用域拓展到了派生類中,在派生類中可以直接使用,假如派生類中只想繼承基類中不帶參數(shù)的函數(shù)該如何呢?這時(shí)使用using聲明可能會(huì)將帶參數(shù)的函數(shù)同時(shí)給引入進(jìn)來(lái),而無(wú)法解決此類問(wèn)題。此處可以通過(guò)轉(zhuǎn)調(diào)函數(shù)實(shí)現(xiàn),如下。

    2.5 使用轉(zhuǎn)掉函數(shù)

    私有繼承加上轉(zhuǎn)調(diào)函數(shù)可以完美解決using聲明不能解決的只繼承帶不參數(shù)的函數(shù),例子如下:

    // Base基類同上void Base::mFun1(){ std::cout << "Base mFun1" << std::endl;}class Derived: private Base {public: virtual void mFun1() { std::cout << "Derieved mFun1" << std::endl; Base::mFun1(); }};

    使用Demo進(jìn)行測(cè)試

    int main() { Derived der; der.mFun1(); // call Derived mFun1 // der.mFun1(1.0); // error no matching function return 0;}

    運(yùn)行結(jié)果:

    Derieved mFun1Base mFun1

    參考:

    1.Effective C++ Item33

    2.解析C++隱藏與覆蓋Oragen的博客-CSDN博客c++隱藏和覆蓋

    3.作用域_百度百科 (baidu.com)

    備注:

    歡迎大家多多指教,喜歡的大家可以點(diǎn)擊關(guān)注本賬號(hào)或者微信公眾號(hào):軟件系統(tǒng)安全,后續(xù)將不定期更新C++相關(guān)的內(nèi)容

    鄭重聲明:本文內(nèi)容及圖片均整理自互聯(lián)網(wǎng),不代表本站立場(chǎng),版權(quán)歸原作者所有,如有侵權(quán)請(qǐng)聯(lián)系管理員(admin#wlmqw.com)刪除。
    用戶投稿
    上一篇 2022年8月8日 10:19
    下一篇 2022年8月8日 10:19

    相關(guān)推薦

    聯(lián)系我們

    聯(lián)系郵箱:admin#wlmqw.com
    工作時(shí)間:周一至周五,10:30-18:30,節(jié)假日休息