• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            C++分析研究  
            C++
            日歷
            <2012年11月>
            28293031123
            45678910
            11121314151617
            18192021222324
            2526272829301
            2345678
            統計
            • 隨筆 - 92
            • 文章 - 4
            • 評論 - 4
            • 引用 - 0

            導航

            常用鏈接

            留言簿

            隨筆檔案

            文章檔案

            搜索

            •  

            最新評論

            閱讀排行榜

            評論排行榜

             
              在C++中為什么輸入輸出流不能重載為類成員函數?

              假如說operator 《 ()這是一個成員函數,mealtime是一個類Time的私有成員,那么如我們看到的,如下一個輸出語句:cout《mealtime;將被編譯器處理為發送一條消息到cout,cout.operator《(mealtime);這表示operator 《必須是類ostream的一個成員,而不是類Time的一個成員。然而,即使能將這個新函數添加到標準ostream中,仍然不希望破壞標準的庫,因此operator 《必然是一個普通函數,這表示如下輸出語句:cout《mealtime將被編譯器看作函數調用operator《(cout,mealtime);這樣operator《()必須具有兩個形參,第一個是ostream類,第二個是Timer類。

              大部份的標準庫實現中,對ostream,istream類體系采用了構造函數保護繼承的方式……致使即使以繼承的方式來擴展流類,也會在對象實例化時遭遇阻礙……

              另一方面,標準庫中的流類,其插入符函數沒有聲明為虛函數,因此子類不能對其實現進行覆蓋,所以也使成員函數重載遭遇到實質的困難……

              總的來說,C++標準I/O庫非常繁雜且難,其實現思想很多都與常規的OOP有所出入……在使用的時候要謹慎,并最好遵從慣例……

              為什么C++賦值運算符不能被繼承?

              1,每一個類對象實例在創建的時候,如果用戶沒有定義“賦值運算符重載函數”,那么,編譯器會自動生成一個隱含和默認的“賦值運算符重載函數”。所以,B1的實際上的聲明應該類似于下面這種情況:

              class A1

              {

              public:

              int operator=(int a)

              {

              return 8;

              }

              int operator+(int a)

              {

              return 9;

              }

              };

              class B1 : public A1

              {

              public:

              B1& operator =(const B1& robj); // 注意這一行是編譯器添加的

              int operator-(int a)

              {

              return 7;

              }

              };

              2,C++標準規定:如果派生類中聲明的成員與基類的成員同名,那么,基類的成員會被覆蓋,哪怕基類的成員與派生類的成員的數據類型和參數個數都完全不同。顯然,B1中的賦值運算符函數名operator =和基類A1中的operator =同名,所以,A1中的賦值運算符函數int operator=(int a);被B1中的隱含的賦值運算符函數B1& operator =(const B1& robj);所覆蓋。 A1中的int operator=(int a);函數無法被B1對象訪問。 www.liuhebao.com

              3,程序中語句v = 2實際上相當于v.operator =(2);,但是A1中的int operator=(int a);已經被覆蓋,無法訪問。而B1中默認的B1& operator =(const B1& robj);函數又與參數2的整數類型不相符,無法調用。

              4,為了確認B1中默認的B1& operator =(const B1& robj);函數的存在性,可以用以下代碼驗證:

              B1 b;

              B1 v;

              v = b; // OK, 相當于調用v.operator =(b);STA

              5,所以,“賦值運算符重載函數”不是不能被派生類繼承,而是被派生類的默認“賦值運算符重載函數”給覆蓋了。

              這就是C++賦值運算符重載函數不能被派生類繼承的真實原因!

              關于本帖問題正確性的解釋

              C++程序員的必讀經典《Effective C++》這么說:

              條款45: 弄清C++在幕后為你所寫、所調用的函數

              一個空類什么時候不是空類? ---- 當C++編譯器通過它的時候。如果你沒有聲明下列函數,體貼的編譯器會聲明它自己的版本。這些函數是:一個拷貝構造函數,一個賦值運算符,一個析構函數,一對取址運算符。另外,如果你沒有聲明任何構造函數,它也將為你聲明一個缺省構造函數。所有這些函數都是公有的。換句話說,如果你這么寫:

              class Empty{};

              和你這么寫是一樣的:

              class Empty {

              public:

              Empty(); // 缺省構造函數

              Empty(const Empty& rhs); // 拷貝構造函數

              ~Empty(); // 析構函數 ---- 是否

              // 為虛函數看下文說明

              Empty&

              operator=(const Empty& rhs); // 賦值運算符

              Empty* operator&(); // 取址運算符

              const Empty* operator&() const;

              };

              但是Effective C++依然不能作為最后的判決。讓我們從C++的“憲法”中尋找答案…

              ISO/IEC 14882是C++的國際標準。該標準于1998年9月1日通過并且定案。當然,這個標準已經不是最新標準了,但這個標準卻是目前最被廣泛支持的C++標準。所以,我一向稱之為C++的“憲法”。

              C++“憲法”第12章 Special Member Functions (第185頁)開宗明義:

              The default constructor, copy constructor and copy assignment operator, and destructor are special member functions. The implementation will implicitly declare these member functions for a class type when the program does not explicitly declare them, except as noted in 12.1. The implementation will implicitly define then if they are used, as specified in 12.1, 12.4 and 12.8. Programs shall not define implicitly-declared special member functions. Programs may explicitly refer to implicitly declared special member functions.

              譯文:

              缺省構造函數,拷貝構造函數,拷貝賦值函數,以及析構函數這四種成員函數被稱作特殊的成員函數。如果用戶程序沒有顯式地聲明這些特殊的成員函數,那么編譯器實現將隱式地聲明它們。12.1中有特別解釋的例外。如果用戶程序調用了這些特殊的成員函數,那么編譯器就會定義這些特殊的成員函數,在12.1,12.4,12.8中分別規定了編譯器對這些函數的定義方式。用戶程序不能定義隱式聲明的特殊成員函數。用戶程序可以顯式地調用隱式聲明的特殊成員函數。

              譯注:

              根據C++標準的規定:

              聲明(Declare)代表頭文件中的那部分代碼,比如下面就是一個聲明:

              class A

              {

              public:

              A();

              }

              定義(Define)代表源文件中的代碼,比如下面就是一個定義:

              A::A()

              {}

              綜上所述,可知,第一個說法是正確的。

              關于第二個說法的正確性,可參見C++“憲法”3.3.7 Name Hiding (第28頁)(由于我手上的C++“憲法”是掃描版,無法直接拷貝文字,且文字較多,懶得輸入了。)

              第3,4,5點說法都是常識性的知識,可以直接驗證。
            posted on 2012-11-26 18:14 HAOSOLA 閱讀(253) 評論(0)  編輯 收藏 引用
             
            Copyright © HAOSOLA Powered by: 博客園 模板提供:滬江博客
            PK10開獎 PK10開獎
            久久综合给久久狠狠97色| 99久久免费国产精品| 久久久久久精品无码人妻| 久久精品国产2020| 色欲久久久天天天综合网精品| 久久国产高潮流白浆免费观看| 一本一道久久精品综合| 午夜精品久久久久久影视riav| 亚洲成色www久久网站夜月| 国产国产成人精品久久| 久久人人超碰精品CAOPOREN| 久久精品无码一区二区WWW| 久久精品国产亚洲麻豆| 亚洲精品美女久久777777| 久久精品国产99国产精品澳门| 亚洲国产精品无码久久九九| 99久久婷婷免费国产综合精品| 久久综合九色欧美综合狠狠 | 国产成人无码精品久久久性色 | 三上悠亚久久精品| 久久久99精品成人片中文字幕 | 91久久福利国产成人精品| 思思久久精品在热线热| 国产精品成人99久久久久91gav | 国产精品一区二区久久不卡| 午夜精品久久久久成人| 国产福利电影一区二区三区久久久久成人精品综合 | 国产AV影片久久久久久| 久久精品国产亚洲AV无码偷窥| 久久午夜综合久久| 国产福利电影一区二区三区久久久久成人精品综合 | 国产精品一区二区久久精品涩爱| 亚洲国产成人久久精品动漫| 人妻精品久久无码专区精东影业| 久久久久无码中| 久久久久久A亚洲欧洲AV冫| 国产真实乱对白精彩久久| 成人午夜精品久久久久久久小说 | 国产国产成人精品久久| 精品久久久久久亚洲精品| 久久精品中文騷妇女内射|