<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    so true

    心懷未來,開創(chuàng)未來!
    隨筆 - 160, 文章 - 0, 評論 - 40, 引用 - 0
    數(shù)據(jù)加載中……

    關(guān)于public,protected和private三個關(guān)鍵詞的理解

    關(guān)于public,protected和private三個關(guān)鍵詞的理解

    可以說,接觸C++的時間也不短了,但是對這三個詞一直都是一知半解,直到今天,才覺得自己基本上領(lǐng)悟了這個三個關(guān)鍵詞的真正含義,而且也能把握的更準(zhǔn)確一些,而我理解這三個詞的角度應(yīng)該說是很獨特很獨特的,沒準(zhǔn)世界上沒有其他的人會這樣“有見地”的去如此理解,哈哈,好了,閑話少說,下面就給出我的理解:
    分三個層次:即對于類自身而言;對類外部而言;對子類繼承方式而言。

    對于類自身而言:
    public代表完全不受限制;
    protected代表這些東東(函數(shù)或者成員)除了我自己用之外還能給我的后代用,當(dāng)然我指得是在后代的內(nèi)部用而不是通過后代去暴露我的隱私(注意,這些東東是我的,我有權(quán)利決定為它們作主,既然我已經(jīng)表態(tài)了要給我的后代用,因此我就不會理會我的后代是用何種方式<public,protected還是private都無所謂>來繼承我);
    private代表這些東東只能我自己用啦,別人再也不要覬覦它們了,不管是誰(包括我的后代)。

    對于類外部而言:
    當(dāng)沒有繼承時,只有被聲明為public的東東才能“.”或者“->”出來,其他的兩種聲明方式都不可以向外部暴露;當(dāng)存在繼承時,也很簡單,只有這個東東的“從聲明到一步步的繼承方式都為public”時,才可以向外部暴露,除此之外就別無它法了。

    對于子類的繼承方式而言:
    public繼承方式,啥都不改變,基類的成員或函數(shù)聲明時啥樣就是啥樣;
    protected繼承方式,基類給我的東東(也就是用public或protected修飾的東東)都被變成protected的了,哈哈,雖然作為子類我沒啥牛的,但是現(xiàn)在至少我通過自己的努力把基類的public都給搞成protected的啦,因此要是有一些類再從我這里派生的話,基類的public的東東它們都只能當(dāng)作protected的來用啦,別再想暴露基類的這些public的東東了,因為我已經(jīng)做了手腳(用protected繼承),從而限制了我的后代的行為;
    private繼承方式,把基類給我的東東都變成private的了,哈哈,這下我的后代得哭了,因為基類的好東東它們啥也不能用了,看來我雖然是子類,還是有一定權(quán)利的喲,至少我可以控制我后代的行為。
    對于這部分,相對于其他兩部分來說,也是最難理解的,因此我再多說兩句,說到本質(zhì)上,關(guān)于基類,當(dāng)前類,當(dāng)前類的子類這三者而言,既然它們都是在一條鏈條上,因此彼此之間肯定是有關(guān)系的,這種關(guān)系就表現(xiàn)在上級對下級的控制上,也就是上級直接影響的對象是緊挨著它的下級,就是通過這樣的方式(上級在自身所擁有的東東上施加的各種修飾符;對于那些不是上級自身定義的東東<而是繼承過來的東東>,雖然沒有辦法直接施加修飾符,但是可以通過用不同的修飾符繼承來達(dá)到控制的效果)來一環(huán)扣一環(huán)的影響下去的。
    因此,我自身定義的東東我說了算,基類的東東就只有基類說了算啦,準(zhǔn)備要給子類的東東是由基類和我來一起說了算的。因此舉個例子來說的話,A中有個public或protected的變量m_nA,B通過private的方式繼承了A,那么m_nA在B內(nèi)當(dāng)然是可以隨便使用的了,但是如果C從B那里繼承,即便是public繼承,那么C中是不可以使用m_nA的,因為B已經(jīng)壞壞的通過private繼承方式把m_nA這個資源給截獲了,別人不能再用了,哈哈,B太壞了。
    總結(jié)出一句很經(jīng)典的話:不同的基承方式只能影響子類(子類能不能使用這些好東東)和外部(這些東東能不能暴露給外部),而對自身沒有影響。

    為了把這篇文章便得豐滿一些,我再拽點別的吧,當(dāng)然也是與這三個詞相關(guān)的很重要的東西,哈哈。

    在這三個詞中,我愿意把public自己歸為一類,而把另兩個歸為一類,因為這兩類有本質(zhì)的區(qū)別,首先來說說public,D : public B,代表的是一種isa的關(guān)系,也就是“D是一個B”,就像說“XXX是一個人”一樣正確,提到public繼承,你能想到什么?你可以問問自己,我估計你想到的應(yīng)該是“基類的函數(shù)或者成員在子類的可見性之類的”,但是我問大家一個問題“我們可以隨意的把兩個類X和Y拿過來,然后讓Y: public X嗎?”你當(dāng)然會說不行,為啥不行?我告訴你答案:從語法上來說,這么做是完全可行的,但從語義上來理解是不可行的,比如基類是人,你總不能從這個基類繼承出一個磚頭的子類來吧?那么如何來驗證這種繼承的可行性呢?說到這里大家就必須清楚繼承或者派生的本質(zhì)含義了——D是B;D更具體,B更一般化;“只要是B能做的事情,D一定要也能做才行”。看到它的本質(zhì)了吧?那么知道了這些就太容易說出為啥磚頭不能繼承人了,因為人能做的事情磚頭是做不了的。因此我們通常在面向?qū)ο笾刑岬降幕卸际侵傅膒ublic,而protected和private這兩種方式已經(jīng)完全破壞了基承的語義和體系,它們的存在只是為了滿足特定的需要,在這兩種方式之下,D和B沒有任何概念上的關(guān)系,我們不能說D就是B或者其他用于描述他們彼此之間關(guān)系的話,因為他們已經(jīng)不存在任何關(guān)系了。那么這兩種方式的存在是要做什么呢?答案是:他們要描述一種“根據(jù)某物實現(xiàn)(is-implemented-in-terms-of)”的關(guān)系,也就是說,D要利用B的成員函數(shù)的代碼或成員變量來構(gòu)建自身,D只是為了從B那里得到一些實惠和好處。因此在這兩種繼承方式下,不能夠再類型轉(zhuǎn)化了(因為B和D已經(jīng)沒有關(guān)系了,D不是B,B更不是D),進(jìn)而帶來的一個直接后果就是我們不能利用通常的方法來進(jìn)行多態(tài)了,比如在B和D中都定義一個virtual void test()的函數(shù),然后試圖利用D d; B* pb=&d; pb->test()來調(diào)用D的test函數(shù),這是根本行不通的因為B* pb=&d這一步已經(jīng)是錯的了,這種轉(zhuǎn)型會失敗。既然提到了多態(tài),那就順帶說一下,只要是發(fā)生在子類和基類之間,只要是在基類中被virtual聲明的函數(shù)就都可以實現(xiàn)多態(tài)性,而實現(xiàn)的方法是“只要你可以通過一定的方法把一個對多態(tài)函數(shù)的調(diào)用給暴露出去即可”;從根本上來說,在基類中聲明函數(shù)為virtual,就是為了允許子類能夠重新定義該函數(shù)的,大家都知道類的成員函數(shù)內(nèi)部(除了被static函數(shù)修飾的之外)都是隱含了一個this指針的,當(dāng)這個進(jìn)入到一個成員函數(shù)內(nèi)部時,只要滿足“this實際指向的是子類,且基類已經(jīng)把某個函數(shù)定義為virtual的了,當(dāng)然子類中確實已經(jīng)override了該函數(shù),然后后就可以快樂的實現(xiàn)多態(tài)了”。下面我就給出一個在如此“艱難”的困境下,多態(tài)依然可以突破層層束縛完成其職責(zé)的一段代碼,來吧,欣賞一下:
    class P1{
     virtual int foo(){return 10;}
    public:
     void test(){cout<<foo()<<endl;}
    };
    class P2 : private P1{
     virtual int foo(){return 20;}
    public:
     void haha(){test();}
    };
    (new P2)->haha();//輸出竟然是20,成功應(yīng)用了多態(tài)性,注意這里面隱藏了兩個private,因此是三個private的限制。

    最后再說說virtual繼承的方式,其實這個東西沒啥奇怪的,主要就是用在鉆石型的多重繼承問題中,比如B和C繼承自A,而D又繼承自B和C,因此構(gòu)成一個鉆石,如果不加任何其他處理的話,那么在D中就會有兩份A,這顯然不對,因此為了防止此情況出現(xiàn),就需要B和C在繼承A的時候,要用virtual這種繼承方式了,這樣就可以保證在D中只有一份A而不是兩份。還有一點需要針對virtual繼承來說的就是“初始化這樣一個基類A時,要把初始化的代碼放在最最深的子類初始化處”,對于通常的繼承體系初始化,也是一種一環(huán)扣一環(huán)的去操作,也就是第N層子類初始化時負(fù)責(zé)N-1層的類,而N-1層的類在初始化時負(fù)責(zé)N-2層的,依次上溯。但是對于基類被virtual繼承的情況,比如它出現(xiàn)在第M層,那么除了要在第M+1層初始化代碼中給它初始化外,還需要在M+2,M+3,...,直至最最深的第N層處的初始化代碼中給它初始化,也就是需要在多個地方填寫它的初始化代碼,大家都知道一個類只能被初始化一次,那么對于它而言,咱們給它寫了這么多用于初始化的代碼,它到底調(diào)用哪一份來初始化自己呢,其實很簡單,就是隨著你定義的那個類走,比如你定義了一個出現(xiàn)在第K層的(M<=K<=N)某個類,自然這個類有一份用于初始化它的代碼,那么OK,就用這份代碼就可以,而不會依次調(diào)用從K層到M層的所有初始化代碼。

    posted on 2008-07-12 14:19 so true 閱讀(967) 評論(1)  編輯  收藏 所屬分類: C&C++

    評論

    # re: 關(guān)于public,protected和private三個關(guān)鍵詞的理解  回復(fù)  更多評論   

    開開心心學(xué)到了知識!樓主太棒了,這比那些晦澀難懂的書強(qiáng)多了!強(qiáng)烈推薦!!!
    2008-07-14 21:46 | pig
    主站蜘蛛池模板: 一本岛v免费不卡一二三区| 亚洲精品97久久中文字幕无码| 亚洲宅男天堂a在线| 最好看最新的中文字幕免费| 久久精品国产96精品亚洲 | 亚洲精品乱码久久久久66| 国产精品免费久久久久影院| 亚洲日韩在线观看免费视频| 亚洲免费视频一区二区三区| 亚洲精品午夜国产VA久久成人| 国产va免费观看| 亚洲精品无码专区久久久| 日本三级在线观看免费| 亚洲免费视频在线观看| 久久久久高潮毛片免费全部播放| 亚洲色偷偷偷网站色偷一区| h视频在线免费看| 亚洲一区精彩视频| 日韩免费电影在线观看| 日韩色视频一区二区三区亚洲 | 亚洲精品又粗又大又爽A片| 日本不卡免费新一二三区| 边摸边吃奶边做爽免费视频99| 亚洲一级特黄大片在线观看| 丝瓜app免费下载网址进入ios| 久久精品国产亚洲av麻| 日本片免费观看一区二区| 国产精品亚洲一区二区麻豆| 国产无遮挡又黄又爽免费视频| 日韩在线观看视频免费 | 亚洲另类自拍丝袜第五页| 免费一级毛片清高播放| eeuss影院ss奇兵免费com| 亚洲av无码一区二区三区不卡| 91精品全国免费观看含羞草| 亚洲精品福利你懂| 国产免费黄色大片| a视频在线观看免费| 亚洲精品成人图区| 午夜毛片不卡高清免费| 九九免费久久这里有精品23|