【effetive C++ 筆記 】條款23:寧以non-member, non-friend替換member函數

根據面向對象守則,數據應該儘可能被封裝,類中成員函數friend函數的封裝性要比非成員函數的封裝性低。爲什麼呢?這是因爲越少的代碼能夠訪問對象內的數據,那麼越多的數據能夠被封裝,我們也能夠越能自由地改變對象的數據,這樣一旦改變成員數據的話能夠將其他的改動變的最低。
非成員函數非友元函數能夠實現較大的封裝性,這是因爲它們的存在並不增加能夠訪問class中private成員的數量。
假設有一個類CWebBrowser:

class CwebBrowser
    {
    public:
        CwebBrowser(){}
        ~CwebBrowser(){}
        void clearCahe();
        void clearHistory();
    private:
    };

我們想設計一個函數來調用clearCache() 和 clearHistory()函數。可以在類中定義一個clearall() 函數,也可以如下實現:

void clearall(CwebBrowser& wb)
    {
        wb.clearCahe();
        wb.clearHistory();
    }

在類外通過對象調用兩個clear函數。這種做法能夠帶來更好的封裝性。我們將這個函數叫做類CwebBrowser的工具函數。但是這樣做不保證這個工具函數不成爲其他類的成員。所以一般做法是將類和該函數放在一個同命名空間裏。所謂命名空間是爲了將一些全局實體分隔開來,避免重複定義的情況出現。比如:

namespace ns1
{
    int a;
    double b;
}

ns1的成員包括a 和 b , 但是a,b仍然是全局變量,僅僅是把額外加了一個命名空間ns1這個範圍而已。

通常不同的用戶關注點不同,比如在這個關於瀏覽器的CwebBrowser類中,有的用戶關注書籤,有的用戶關注cookie。用命名空間還可以用不同的頭文件表明不同的“關注點”。
具體做法是:
在webbrowser.h文件中定義了一個命名空間,由CwebBrowser類和clearall()函數構成。

using namespace std;
namespace WebBrowserStuff{
    class CwebBrowser
    {
    public:
        CwebBrowser(){}
        ~CwebBrowser(){}
        void clearCahe();
        void clearHistory();
    private:
    };

    void CwebBrowser::clearCahe()
    {
        cout << "Cache cleared!"<< endl;
    }

    void CwebBrowser::clearHistory()
    {
        cout << "History cleared!" << endl;
    }

    void clearall(CwebBrowser& wb)
    {
        wb.clearCahe();
        wb.clearHistory();
    }
}

在webbrowserbookmarks.h 中往命名空間中再添加函數:

using namespace std;

//往namespace裏添加一個函數addbookmarks()
namespace WebBrowserStuff
{
    void addbookmarks()
    {
        cout << "add a book mark successfully!" << endl;
    }

}

還可以在另一個webbrowserothers.h中再添加函數:

using namespace std;

namespace WebBrowserStuff
{
    void addsomething()
    {
        cout << "add something succesfully!" << endl;
    }
}

main函數:

#include <iostream>
#include "webbrowser.h"
#include "webbrowserbookmarks.h"
#include "webbrowserothers.h"

int  main()
{   

    WebBrowserStuff::CwebBrowser web;
    WebBrowserStuff::addbookmarks();
    WebBrowserStuff::addsomething();
    WebBrowserStuff::clearall(web);
    system("pause");
    return 0;
}

這樣便於用戶擴展不同的工具函數,只需要添加一個頭文件聲明就行。

發佈了30 篇原創文章 · 獲贊 23 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章