<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                # Item 22: 將數據成員聲明為 private 作者:Scott Meyers 譯者:fatalerror99 (iTePub's Nirvana) 發布:http://blog.csdn.net/fatalerror99/ 好了,先公布一下計劃。首先,我們將看看為什么數據成員不應該聲明為 public。然后,我們將看到所有反對 public 數據成員的理由同樣適用于 protected 數據成員。這就導出了數據成員應該是 private 的結論,至此,我們就結束了。 那么,public 數據成員,為什么不呢? 我們從先從語法一致性開始(參見 Item 18)。如果數據成員不是 public 的,客戶訪問一個對象的唯一方法就是通過成員函數。如果在 public 接口中的每件東西都是一個函數,客戶就不必絞盡腦汁試圖記住當他們要訪問一個類的成員時是否需要使用圓括號。他們只要使用就可以了,因為每件東西都是一個函數。一生堅持這一方針,能節省很多撓頭的時間。 但是也許你不認為一致性的理由是強制性的。使用函數可以讓你更加精確地控制成員的可存取性的事實又怎么樣呢?如果你讓一個數據成員為 public,每一個人都可以讀寫訪問它,但是如果你使用函數去得到和設置它的值,你就能實現禁止訪問,只讀訪問和讀寫訪問。嘿嘿,如果你需要,你甚至可以實現只寫訪問: ``` class AccessLevels { public: ... int getReadOnly() const { return readOnly; } void setReadWrite(int value) { readWrite = value; } int getReadWrite() const { return readWrite; } void setWriteOnly(int value) { writeOnly = value; } private: int noAccess; // no access to this int int readOnly; // read-only access to this int int readWrite; // read-write access to this int int writeOnly; // write-only access to this int }; ``` 這種條分縷析的訪問控制很重要,因為多數數據成員需要被隱藏。每一個數據成員都需要一個 getter 和 setter 的情況是很罕見的。 還不相信嗎?那么該拿出一門重炮了:封裝。如果你通過一個函數實現對數據成員的訪問,你可以在以后用一個計算來替換這個數據成員,使用你的類的人不會有任何察覺。 例如,假設你為一個監視通過的汽車的速度的自動設備寫一個應用程序。每通過一輛汽車,它的速度就被計算,而且那個值要加入到迄今為止收集到的所有速度數據的集合中: ``` class SpeedDataCollection { ... public: void addValue(int speed); // add a new data value double averageSoFar() const; // return average speed ... }; ``` 現在考慮成員函數 averageSoFar 的實現:實現它的辦法之一是在類中用一個數據成員來實時變化迄今為止收集到的所有速度數據的平均值。無論何時 averageSoFar 被調用,它只是返回那個數據成員的值。另一個不同的方法是在每次調用 averageSoFar 時重新計算它的值,通過分析集合中每一個數據值它能做成這些事情。 第一種方法(保持一個實時變化的值)使每一個 SpeedDataCollection 對象都比較大,因為你必須為持有實時變化的平均值,累計的和以及數據點的數量分配空間。可是,averageSoFar 能實現得非常高效,它僅僅是一個返回實時變化的平均值的 inline 函數(參見 Item 30)。反過來,無論何時被請求都要計算平均值使得 averageSoFar 的運行比較慢,但是每一個 SpeedDataCollection 對象都比較小。 誰能說哪一個最好?在內存非常緊張的機器(例如,一個嵌入式道旁設備)上,以及在一個很少需要平均值的應用程序中,每次都計算平均值可能是較好的解決方案。在一個頻繁需要平均值的應用程序中,速度是基本的要求,而且內存不成問題,保持一個實時變化的平均值更為可取。這里的重點在于通過經由一個成員函數訪問平均值(也就是說,通過將它封裝),你能互換這兩個不同的實現(也包括其他你可能想到的),對于客戶,最多也就是必須重新編譯。(你可以用在后面的 Item 31 中記述的技術來消除這個麻煩。) 將數據成員隱藏在功能性的接口之后能為各種實現提供彈性。例如,它可以在讀或者寫的時候很簡單地通報其他對象,可以檢驗類的不變量以及函數的前置或后置條件,可以在多線程環境中執行同步任務,等等。從類似 Delphi 和 C# 的語言來到 C++ 的程序員會認同這種類似那些語言中的“屬性”的等價物的功能,雖然需要附加一個帶圓括號的額外的 set。 關于封裝的要點可能比它最初顯現出來的更加重要。如果你對你的客戶隱藏你的數據成員(也就是說,封裝它們),你就能確保類的不變量總能被維持,因為只有成員函數能影響它們。此外,你預留了以后改變你的實現決策的權力。如果你不隱藏這樣的決策,你將很快發現,即使你擁有一個類的源代碼,你改變任何一個 public 的東西的能力也是非常有限的,因為有太多的客戶代碼將被破壞。public 意味著沒有封裝,而且幾乎可以說,沒有封裝意味著不可改變,尤其是被廣泛使用的類。但是仍然被廣泛使用的類大多數都是需要封裝的,因為它們可以從用一種更好的實現替換現有實現的能力中獲得最多的益處。 反對 protected 數據成員的理由是類似的。實際上,它是一樣的,雖然起先看起來似乎不那么清楚。關于語法一致性和條分縷析的訪問控制的論證就像用于 public 一樣可以應用于 protected,但是關于封裝又如何呢?難道 protected 數據成員不比 public 數據成員更具有封裝性嗎?實話實說,令人驚訝的答案是它們不。 Item 23 解釋了如果某物發生了變化,某物的封裝與可能被破壞的代碼數量成反比。于是,如果數據成員發生了變化(例如,如果它被從類中移除(可能是為了替換為計算,就像在上面的 averageSoFar 中)),數據成員的封裝性與可能被破壞的代碼數量成反比。 假設我們有一個 public 數據成員,隨后我們消除了它。有多少代碼會被破壞呢?所有使用了它的客戶代碼,其數量通常大得難以置信。從而 public 數據成員就是完全未封裝的。但是,假設我們有一個 protected 數據成員,隨后我們消除了它。現在有多少代碼會被破壞呢?所有使用了它的派生類,典型情況下,代碼的數量還是大得難以置信。從而 protected 數據成員就像 public 數據成員一樣沒有封裝,因為在這兩種情況下,如果數據成員發生變化,被破壞的客戶代碼的數量都大得難以置信。這并不符合直覺,但是富有經驗的庫實現者會告訴你,這是千真萬確的。一旦你聲明一個數據成員為 public 或 protected,而且客戶開始使用它,就很難再改變與這個數據成員有關的任何事情。有太多的代碼不得不被重寫,重測試,重文檔化,或重編譯。從封裝的觀點來看,實際只有兩個訪問層次:private(提供了封裝)與所有例外(沒有提供封裝)。 Things to Remember 聲明數據成員為 private。它為客戶提供了訪問數據的語法層上的一致,提供條分縷析的訪問控制,允許不變量被強制,而且為類的作者提供了實現上的彈性。 protected 并不比 public 的封裝性強。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看