程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> Item 23:非成員非友元函數好於成員函數 Effective C++筆記

Item 23:非成員非友元函數好於成員函數 Effective C++筆記

編輯:C++入門知識

Item 23:非成員非友元函數好於成員函數 Effective C++筆記


Item 23: Prefer non-member non-friend functions to member functions

在類的是實現中,常常會面臨成員函數和非成員函數的選擇。比如一個浏覽器類:

class WebBrowser{
public:
  void clearCache();
  void clearCookies();
  void clearHistory();
};

此時你要實現一個clearEverything()有兩種方式:

class WebBrowser{
public:
  void clearEverything(){
    clearCache();
    clearCookies();
    clearHistory();
  }
}
// 或者使用非成員函數:
void clearEverything(WebBrowser& wb){
  wb.clearCache();
  wb.clearCookies();
  wb.clearHistory();
}

哪種更好呢?面向對象原則指出,數據和數據上的操作應當綁定在一起,那麼前者更好。 這是對面向對象的誤解,面向對象設計的精髓在於封裝,數據應當被盡可能地封裝。 相比於成員函數,非成員函數提供了更好的封裝,包的靈活性(更少的編譯依賴),以及功能擴展性。

封裝性

封裝就是對外界隱藏的意思。如果數據被越好地封裝,那麼越少的東西可以看到它,我們便有更大的靈活性去改變它。這是封裝帶來的最大的好處:給我們改變一個東西的靈活性,這樣的改變只會影響到有限的客戶。

作為粗粒度的估計,數據的封裝性反比於可訪問該數據的函數數量。這些函數包括成員函數、友元函數和友元類中的函數。 因此非成員非友元函數會比成員函數提供更好的封裝, 我們應該選擇clearEverything()的第二種實現。

Item22提到,如果一個數據成員不是私有的,那麼將會有無限數量的函數可訪問它。

這裡有兩點值得注意:

  1. 友元函數和成員函數是一樣的,因為友元函數也可以訪問私有數據成員,它和成員函數對封裝具有相同的影響。
  2. 非成員函數並不意味著它不可以是其他類的成員函數。尤其是在像Java,C#之類的語言中,函數必須定義在類中。
  3. 靜態成員函數也是不錯的選擇。因為靜態函數不能訪問對象成員,因此不會影響對象的封裝。

    擴展性

    在C++中,可以把這些非成員函數定義在相同的命名空間下。 但問題又來了:這些在命名空間下的函數並不在類中,它們會被傳播到所有的源文件中。 而客戶並不希望為了使用幾個工具函數,就對這樣一個龐大的命名空間產生編譯依賴。 因此我們可以將不同類別的工具函數放在不同的頭文件中,客戶可以選擇它想要的那部分功能:

    // file: webbrowser.h
    namespace WebBrowserStuff{
      class WebBrowser{};
    }
    
    // file: webbrowser-bookmarks.h
    namespace WebBrowserStuff{
      ...
    }
    
    // file: webbrowser-cookies.h
    namespace WebBrowserStuff{
      ...
    }
    

    這也是C++標准庫的組織方式,std命名空間下的所有東西都被分在了不同的頭文件中:, , 等。這樣客戶代碼只對它引入的那部分功能產生編譯依賴。 為了做到這一點,這些工具函數必須是非成員函數,因為類作為整體必須在一個文件中進行定義。

    同一命名空間不同頭文件的組織方式,也為客戶擴展工具函數提供了可能。 客戶可以在同一命名空間下定義他自己的工具函數, 這些函數便會和既有工具函數天然地集成在一起。 這也是成員函數無法做到的一個特性,因為類的定義對客戶擴展是關閉的。 即使是子類也不能訪問封裝的(私有)成員數據, 況且有些類不是用來做基類的(見Item 7:將多態基類的析構函數聲明為虛函數)。


     

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved