国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Effective C++ 學(xué)習(xí)筆記 條款23 寧以non-member、non-friend替換member函數(shù)

這篇具有很好參考價(jià)值的文章主要介紹了Effective C++ 學(xué)習(xí)筆記 條款23 寧以non-member、non-friend替換member函數(shù)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

想象有個(gè)class用來(lái)表示網(wǎng)頁(yè)瀏覽器。這樣的class可能提供的眾多函數(shù)中,有一些用來(lái)清除下載元素高速緩存區(qū)(cache of downloaded elements)、清除訪問(wèn)過(guò)的URLs的歷史記錄(history of visited URLs)、以及移除系統(tǒng)中的所有cookies:

class WebBrowser
{
public:
    // ...
    void clearCache();
    void clearHistory();
    void removeCookies();
    // ...
};

許多用戶(hù)會(huì)想一整個(gè)執(zhí)行所有這些動(dòng)作,因此WebBrowser也提供這樣一個(gè)函數(shù):

class WebBrowser
{
public:
    // ...
    void clearEverything();    // 調(diào)用clearCache、clearHistory、removeCookies
    // ...
};

當(dāng)然,這一機(jī)能也可由一個(gè)non-member函數(shù)調(diào)用適當(dāng)?shù)膍ember函數(shù)而提供出來(lái):

void clearBrowser(WebBrowser &wb)
{
    wb.clearCache();
    wb.clearHistory();
    wb.removeCookies();
}

那么,哪一個(gè)比較好呢?是member函數(shù)clearEverything還是non-member函數(shù)clearBrowser?

面向?qū)ο笫貏t要求,數(shù)據(jù)以及操作數(shù)據(jù)的那些函數(shù)應(yīng)該被捆綁在一塊,這意味它建議member函數(shù)是較好的選擇。不幸的是這個(gè)建議不正確。這是基于對(duì)面向?qū)ο笳鎸?shí)意義的一個(gè)誤解。面向?qū)ο笫貏t要求數(shù)據(jù)應(yīng)該盡可能被封裝,然而與直觀相反地,member函數(shù)clearEverything帶來(lái)的封裝性比non-member函數(shù)clearBrowser低。此外,提供non-member函數(shù)可允許對(duì)WebBrowser相關(guān)機(jī)能有較大的包裹彈性(packaging flexibility),而那最終導(dǎo)致較低的編譯相依度,增加WebBrowser的可延伸性。因此在許多方面non-member做法比member做法好。重要的是,我們必須了解其原因。

讓我們從封裝開(kāi)始討論。如果某些東西被封裝,它就不再可見(jiàn)。愈多東西被封裝,愈少人可以看到它。而愈少人看到它,我們就有愈大的彈性去變化它,因?yàn)槲覀兊母淖儍H僅直接影響看到改變的那些人事物。因此,愈多東西被封裝,我們改變那些東西的能力也就愈大。這就是我們首先推崇封裝的原因:它使我們能夠改變事物而只影響有限客戶(hù)。

現(xiàn)在考慮對(duì)象內(nèi)的數(shù)據(jù)。愈少代碼可以看到數(shù)據(jù)(也就是訪問(wèn)它),愈多的數(shù)據(jù)可被封裝,而我們也就愈能自由地改變對(duì)象數(shù)據(jù),例如改變成員變量的數(shù)量、類(lèi)型等等。如何量測(cè)“有多少代碼可以看到某一塊數(shù)據(jù)”呢?我們計(jì)算能夠訪問(wèn)該數(shù)據(jù)的函數(shù)數(shù)量,作為一種粗糙的量測(cè)。愈多函數(shù)可訪問(wèn)它,數(shù)據(jù)的封裝性就愈低。

條款22曾說(shuō)過(guò),成員變量應(yīng)該是private,因?yàn)槿绻鼈儾皇?,就有無(wú)限量的函數(shù)可以訪問(wèn)它們,它們也就毫無(wú)封裝性。能夠訪問(wèn)private成員變量的函數(shù)只有class的member函數(shù)加上friend函數(shù)而已。如果你要在一個(gè)member函數(shù)(它不只可以訪問(wèn)class內(nèi)的private數(shù)據(jù),也可以取用private函數(shù)、enums、typedefs等等)和一個(gè)non-member non-friend函數(shù)(它無(wú)法訪問(wèn)上述任何東西)之間做抉擇,而且兩者提供相同機(jī)能,那么,導(dǎo)致較大封裝性的是non-member non-friend函數(shù),因?yàn)樗⒉辉黾印澳軌蛟L問(wèn)class內(nèi)之private成分”的函數(shù)數(shù)量。這就解釋了為什么clearBrowser(一個(gè)non-member non-friend函數(shù))比clearEverything(一個(gè)member函數(shù))更受歡迎的原因:它導(dǎo)致WebBrowser class有較大的封裝性。

在這一點(diǎn)上有兩件事情值得注意。第一,這個(gè)論述只適用于non-member non-friend函數(shù)。friend函數(shù)對(duì)class private成員的訪問(wèn)權(quán)力和member函數(shù)相同,因此兩者對(duì)封裝的沖擊力道也相同。從封裝的角度看,這里的選擇關(guān)鍵并不在member和non-member函數(shù)之間,而是在member和non-member non-friend函數(shù)之間(當(dāng)然,封裝并非唯一考慮,條款24解釋當(dāng)我們考慮隱式類(lèi)型轉(zhuǎn)換,應(yīng)該在member和non-member函數(shù)之間抉擇)。

第二件值得注意的事情是,只因在意封裝性而讓函數(shù)“成為class的non-member”,并不意味著它“不可以是另一個(gè)class的member”。這對(duì)那些習(xí)慣于“所有函數(shù)都必須定義于class內(nèi)”的語(yǔ)言(如Eiffel、Java、C#)的程序員而言,可能是個(gè)溫暖的慰藉。例如我們可以令clearBrowser成為某工具類(lèi)(utility class)的一個(gè)static member函數(shù)。只要它不是WebBrowser的一部分(或成為其friend),就不會(huì)影響WebBrowser的private成員封裝性。

在C++,比較自然的做法是讓clearBrowser成為一個(gè)non-member函數(shù)并且位于WebBrowser所在的同一個(gè)namespace(命名空間)內(nèi):

namespace WebBrowserStuff
{
    class WebBroser
    {
        // ...
    };
    
    void clearBrowser(WebBrowser &wb);
    // ...
}

然而這不只是為了看起來(lái)自然而已。要知道,namespace和class不同,前者可以跨越多個(gè)源碼文件而后者不能。這很重要,因?yàn)橄馽learBrowser這樣的函數(shù)是個(gè)“提供便利的函數(shù)”,如果它既不是member也不是friend,就沒(méi)有對(duì)WebBrowser的特殊訪問(wèn)權(quán)力,也就只能提供“WebBrowser客戶(hù)以其他方式也能取得”的機(jī)能。舉個(gè)例子,如果clearBrowser不存在,客戶(hù)端就只好自行調(diào)用clearCache、clearHistory、removeCookies。

一個(gè)像WebBrowser這樣的class可能擁有大量便利函數(shù),某些與書(shū)簽(bookmarks)有關(guān),某些與打印有關(guān),還有一些與cookies的管理有關(guān)……通常大多數(shù)客戶(hù)只對(duì)其中某些感興趣。沒(méi)道理一個(gè)只對(duì)書(shū)簽相關(guān)便利函數(shù)感興趣的客戶(hù)卻與例如一個(gè)cookie相關(guān)便利函數(shù)發(fā)生編譯相依關(guān)系。分離它們的最直接做法就是將書(shū)簽相關(guān)便利函數(shù)聲明于一個(gè)頭文件,將cookie相關(guān)便利函數(shù)聲明于另一個(gè)頭文件,再將打印相關(guān)便利函數(shù)聲明于第三個(gè)頭文件,依此類(lèi)推:

// 頭文件“webbrowser.h”——這個(gè)頭文件針對(duì)class WebBrowser自身及WebBrowser核心機(jī)能
namespace WebBrowserStuff
{
    class WebBrowser
    {
        // ...
    };
    // ...    核心機(jī)能,例如幾乎所有客戶(hù)都需要的non-member函數(shù)
}

// 頭文件“webbrowserbookmarks.h”
namespace WebBrowserStuff
{
    // ...    與書(shū)簽相關(guān)的便利函數(shù)
}

// 頭文件“webbrowsercookies.h”
namespace WebBrowserStuff
{
    // ...    與cookie相關(guān)的便利函數(shù)
}
// ...

注意,這正是C++標(biāo)準(zhǔn)庫(kù)的組織方式。標(biāo)準(zhǔn)程序庫(kù)并不是擁有單一、整體、龐大的<C++StankardLibrary>頭文件并在其中內(nèi)含std命名空間內(nèi)的每一樣?xùn)|西,而是有數(shù)十個(gè)頭文件(<vector>、<algorithm>、<memory>等等),每個(gè)頭文件聲明std的某些機(jī)能。如果客戶(hù)只想使用vector相關(guān)機(jī)能,他不需要#include <memory>;如果客戶(hù)不想使用list,也不需要#include <list>。這允許客戶(hù)只對(duì)他們所用的那一小部分系統(tǒng)形成編譯相依(見(jiàn)條款13,其中討論降低編譯依存性的其他做法)。以此種方式切割機(jī)能并不適用于class成員函數(shù),因?yàn)橐粋€(gè)class必須整體定義,不能被分割為片片段段。

將所有便利函數(shù)放在多個(gè)頭文件內(nèi)但隸屬同一個(gè)命名空間,意味客戶(hù)可以輕松擴(kuò)展這一組便利函數(shù)。他們需要做的就是添加更多non-member non-friend函數(shù)到此命名空間內(nèi)。舉個(gè)例子,如果某個(gè)WebBrowser客戶(hù)決定寫(xiě)些與影像下載相關(guān)的便利函數(shù),他只需要在WebBrowserStuff命名空間內(nèi)建立一個(gè)頭文件,內(nèi)含那些函數(shù)的聲明即可。新函數(shù)就像其他舊有的便利函數(shù)那樣可用且整合為一體。這是class無(wú)法提供的另一個(gè)性質(zhì),因?yàn)閏lass定義式對(duì)客戶(hù)而言是不能擴(kuò)展的。當(dāng)然,客戶(hù)可以派生出新class,但derived class無(wú)法訪問(wèn)base class中被封裝的(即private)成員,于是如此的“擴(kuò)展機(jī)能”擁有的只是次級(jí)身份。此外一如條款7所說(shuō),并非所有class都被設(shè)計(jì)用來(lái)作為base class。

請(qǐng)記住:
寧可拿non-member non-friend函數(shù)替換member函數(shù)。這樣做可以增加封裝性、包裹彈性和機(jī)能擴(kuò)充性。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-840006.html

到了這里,關(guān)于Effective C++ 學(xué)習(xí)筆記 條款23 寧以non-member、non-friend替換member函數(shù)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶(hù)投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • Effective C++條款17——以獨(dú)立語(yǔ)句將newed 對(duì)象置入智能指針(資源管理)

    假設(shè)我們有個(gè)函數(shù)用來(lái)揭示處理程序的優(yōu)先權(quán),另一個(gè)函數(shù)用來(lái)在某動(dòng)態(tài)分配所得的widget上進(jìn)行某些帶有優(yōu)先權(quán)的處理: 由于謹(jǐn)記“以對(duì)象管理資源”(條款13)的智慧銘言,processwidget決定對(duì)其動(dòng)態(tài)分配得來(lái)的widget運(yùn)用智能指針(這里采用trl::shared_ptr)。 現(xiàn)在考慮調(diào)用proces

    2024年02月11日
    瀏覽(19)
  • Effective C++條款07——為多態(tài)基類(lèi)聲明virtual析構(gòu)函數(shù)(構(gòu)造/析構(gòu)/賦值運(yùn)算)

    有許多種做法可以記錄時(shí)間,因此,設(shè)計(jì)一個(gè)TimeKeeper base class和一些derived classes 作為不同的計(jì)時(shí)方法,相當(dāng)合情合理: 許多客戶(hù)只想在程序中使用時(shí)間,不想操心時(shí)間如何計(jì)算等細(xì)節(jié),這時(shí)候我們可以設(shè)計(jì)factory (工廠)函數(shù),返回指針指向一個(gè)計(jì)時(shí)對(duì)象。Factory函數(shù)會(huì)“返回

    2024年02月12日
    瀏覽(27)
  • More Effective C++學(xué)習(xí)筆記(1)

    在任何情況下都 不能使用指向空值的引用 。一個(gè)引用必須總是指向某個(gè)對(duì)象,必須有初值。 如果變量指向 可修改,且有可能指向null ,就把變量設(shè)為 指針 ;如果變量 總是必須代表一個(gè)對(duì)象(不可能為null) ,就把變量設(shè)為 引用 。 引用可能比指針更高效 ,因?yàn)椴槐叵裰羔?/p>

    2024年02月12日
    瀏覽(44)
  • effective c++ 筆記

    TODO:還沒(méi)看太懂的篇章 item25 item35 模板相關(guān)內(nèi)容 可以將C++視為以下4種次語(yǔ)言的結(jié)合體: C 面向?qū)ο?模板 STL 每個(gè)次語(yǔ)言都有自己的規(guī)范,因此當(dāng)從其中一個(gè)切換到另一個(gè)時(shí),一些習(xí)慣或守則是可能會(huì)發(fā)生變化的。 用const替換#define有以下2個(gè)原因: #define定義的符號(hào)名稱(chēng)可能沒(méi)

    2024年02月10日
    瀏覽(19)
  • C++筆記-effective stl

    熟悉stl本身 慎重選擇stl容器,每一種stl容器對(duì)應(yīng)不同的使用場(chǎng)景,比如deque往往比vector更加合適 封裝stl容器,積極的使用stl,可以高效的使用它 積極使用其對(duì)應(yīng)迭代器使用的函數(shù),比如做相加運(yùn)算使用accumulate替代for循環(huán),可以更加高效 調(diào)用對(duì)應(yīng)的函數(shù)的時(shí)候,不使用過(guò)于復(fù)

    2024年01月18日
    瀏覽(45)
  • 《Effective C++中文版,第三版》讀書(shū)筆記7

    隱式接口: ? 僅僅由一組有效表達(dá)式構(gòu)成,表達(dá)式自身可能看起來(lái)很復(fù)雜,但它們要求的約束條件一般而言相當(dāng)直接而明確。 顯式接口: ? 通常由函數(shù)的簽名式(也就是函數(shù)名稱(chēng)、參數(shù)類(lèi)型、返回類(lèi)型)構(gòu)成 ? 在源碼中明確可見(jiàn)。 編譯期多態(tài): 在編譯時(shí)才能確定具體調(diào)

    2024年02月09日
    瀏覽(55)
  • effective c++ 43-處理模板化基類(lèi)的名稱(chēng) 筆記

    該節(jié)主要分析了一個(gè)寫(xiě)模板時(shí)常常會(huì)遇到的一個(gè)編譯錯(cuò)誤。 這里有一個(gè)模板基類(lèi),有派生類(lèi)繼承了模板基類(lèi),并調(diào)用了基類(lèi)中的方法,但是編譯器卻會(huì)報(bào)找不該方法,這是怎么回事? 編譯輸出如下: 從編譯的輸出也可以看出,原因是編譯器覺(jué)得 sendClear 含義不明確,編譯器

    2024年02月03日
    瀏覽(29)
  • 《Effective C++ 改善程序與設(shè)計(jì)的55個(gè)具體做法》讀書(shū)筆記

    條款01 視C++為一個(gè)語(yǔ)言聯(lián)邦 C Object-Oriented C++ Template C++ STL C++ 高效編程守則視情況而變化,取決于你使用 C++ 的哪一部分。 條款02 盡量與const,enum,inline替換#define 對(duì)于單純常量,最好以 const 對(duì)象或 enums 替換 #defines 。 對(duì)于形似函數(shù)的宏( macros ),最好改用 inline 函數(shù)替換

    2024年02月12日
    瀏覽(22)
  • 《Effective Python 編寫(xiě)高質(zhì)量Python代碼的59個(gè)有效方法》學(xué)習(xí)筆記2

    盡量用enumerate取代range 用zip()同時(shí)遍歷兩個(gè)迭代器 合理使用try-except-else-finally 如果既要異常向上傳播,又要在異常發(fā)生時(shí)執(zhí)行清理工作,可使用try/finally結(jié)構(gòu) try/except/else結(jié)構(gòu)可以清晰描述哪些異常由自己的代碼處理,哪些傳播到上一級(jí) 無(wú)論try塊是否異常,都可用try/finally復(fù)合

    2023年04月25日
    瀏覽(95)
  • Docker學(xué)習(xí)筆記23

    Docker學(xué)習(xí)筆記23

    Docker Swarm架構(gòu): ? ? ? ? Swarm中以集群(Cluster)為單位進(jìn)行管理,支持服務(wù)層面的操作。 ? ? ? ? 集群是Swarm所管理的對(duì)象。 基本概念: 節(jié)點(diǎn)(Node)為Swarm集群中的一個(gè)Docker Engine實(shí)例。其中管理節(jié)點(diǎn)(Manage Node)負(fù)責(zé)Swarm集群管理并向工作節(jié)點(diǎn)分配任務(wù)。工作節(jié)點(diǎn)(Work No

    2024年02月12日
    瀏覽(14)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包