C++設(shè)計(jì)與聲明超詳細(xì)講解
讓接口被正確使用不易被誤用
除非有好的理由,否則應(yīng)該讓你的types的行為與內(nèi)置types一致,請(qǐng)拿ints做范本
提供行為一致的接口!
阻止誤用的辦法包括建立新類型,限制類型上的操作,束縛對(duì)象值(比如要統(tǒng)計(jì)年月日,限制月的大小在1-12),消除客戶的資源管理責(zé)任(智能指針)
shared_ptr支持定制型刪除器,可被用來(lái)自動(dòng)解除互斥鎖等
寧以pass-by-reference-to-const替換pass-by-value
值傳遞要調(diào)用copy構(gòu)造函數(shù),釋放時(shí)要調(diào)用多次析構(gòu)函數(shù)(有副本),費(fèi)時(shí)
const的必要性:引用傳遞代替值傳遞時(shí),確保不會(huì)對(duì)傳入的數(shù)據(jù)做改變
防止被切割:
class Window{ public: virtual void display(); } class WindowWithScrollBars:public Window{ public: virtual void display(); } void show(Window w){ w.display(); }
當(dāng)用一個(gè)WindowWithScrollBars對(duì)象傳入show時(shí),因?yàn)槭侵祩鬟f,會(huì)導(dǎo)致其特化信息被切割,變成了一個(gè)Window對(duì)象!無(wú)法多態(tài)了!
應(yīng)該如下:傳進(jìn)來(lái)的窗口是什么類型,w就表現(xiàn)出哪種特性
void show(const Window& w){ ... }
說(shuō)到底,引用是指針實(shí)現(xiàn)出來(lái)的,引用傳遞說(shuō)到底也是傳遞的指針,如果有一個(gè)對(duì)象屬于內(nèi)置類型,值傳遞效率會(huì)比引用傳遞效率高一些。
值傳遞對(duì)于內(nèi)置類型和STL的迭代器和函數(shù)對(duì)象來(lái)說(shuō)代價(jià)不貴,其他類型還是選用const引用傳遞好!
必須返回對(duì)象時(shí)
別妄想返回reference
不是所有情況都是引用傳遞好
const A& operator*(const A& rhs){ A result(rhs);//調(diào)用構(gòu)造函數(shù) return result; }
返回了一個(gè)result的引用,但result是一個(gè)局部變量,離開(kāi)作用域就被析構(gòu)了?。?!
引用不能返回一個(gè)局部對(duì)象,否則一敗涂地
一個(gè)必須返回新對(duì)象的函數(shù)的做法是:就讓他返回一個(gè)新對(duì)象唄
const A operator*(const A& rhs){ A result(rhs);//調(diào)用構(gòu)造函數(shù) return A(rhs); }
承受一個(gè)operator*構(gòu)造和析構(gòu)函數(shù)的代價(jià)即可
絕對(duì)不要返回一個(gè)指針或引用指向一個(gè)local stack對(duì)象(出作用域會(huì)被析構(gòu)),或返回引用指向一個(gè)heap-allocated對(duì)象(無(wú)法保證合理的delete),或返回指針或引用指向一個(gè)local static對(duì)象而有可能同時(shí)需要多個(gè)這樣的對(duì)象(一個(gè)指針修改了指向?qū)ο蟮膮?shù)后,其他指針指向的參數(shù)也被修改了)
將成員變量聲明為private
語(yǔ)法一致性:成員變量不是public,用戶只能通過(guò)public里的相應(yīng)函數(shù)來(lái)訪問(wèn)成員變量,用戶使用時(shí)就都有一致的使用規(guī)則(全都要使用小括號(hào)等)
使用函數(shù)可以對(duì)成員變量的處理有更精確的控制,如可以編寫const函數(shù)實(shí)現(xiàn)只讀訪問(wèn),不加const實(shí)現(xiàn)讀寫訪問(wèn)等
封裝性,防止成員變量被更改
假如有一個(gè)public成員變量,我們最終取消了它,所有使用它的代碼都會(huì)被破壞,假如有一個(gè)protected成員變量,我們最終取消了它,所有使用它的派生類都會(huì)被破壞。因此protected其實(shí)并不比public更加具有封裝性
說(shuō)到底,選擇private就好
以non-member non-friend替換member函數(shù)
能夠訪問(wèn)private成員變量的函數(shù)只有class的member函數(shù)加上friend函數(shù),如果要在一個(gè)member函數(shù)(不只可以訪問(wèn)private數(shù)據(jù),也能取用private函數(shù)、enums、typedefs等)和一個(gè)non-member,non-friend函數(shù)做抉擇,較好封裝性的時(shí)后者。因?yàn)樗⒉辉黾幽軌蛟L問(wèn)class內(nèi)private成分的函數(shù)數(shù)量
將所有便利函數(shù)放在多個(gè)頭文件內(nèi)但同屬于一個(gè)命名空間,用戶可以輕松添加這一組便利函數(shù),即可以添加更多的non-member,non-friend函數(shù)到此命名空間
參考C++標(biāo)準(zhǔn)程序庫(kù),vector、algorithm等,導(dǎo)入頭文件再進(jìn)行調(diào)用,即可完成很多事情
non-member
若所有參數(shù)皆需要類型轉(zhuǎn)換,請(qǐng)為此采用non-member函數(shù)
class Rational{ public: Rational(int numerator=0,int denominator=1); int numerator() const; int denominator() const; const Rational operator* (const Rational& rhs) const; } Rational onehalf(1,2); Rational result=onehalf*2;//很好! Rational result=2*onehalf;//不行!
原因在于:
result=onehalf.operator*(2);//發(fā)生了隱式轉(zhuǎn)換 得益于之前沒(méi)有將構(gòu)造函數(shù)聲明為explicit result=2.operator*(onehalf);
2沒(méi)有相應(yīng)的class,沒(méi)有operator*成員函數(shù),當(dāng)然無(wú)法執(zhí)行
結(jié)論為:只有當(dāng)參數(shù)被列于參數(shù)列內(nèi),這個(gè)參數(shù)才是隱式轉(zhuǎn)換的合格參與者
改變做法為將operator*變成non-member函數(shù),允許編譯器在每個(gè)實(shí)參上執(zhí)行隱式轉(zhuǎn)換
operator*是否應(yīng)該成為class的一個(gè)friend函數(shù)呢?否定的,因?yàn)閛perator*完全可以借用Rational的public接口完成任務(wù),這告訴我們:member函數(shù)的反面是non-member,而不是friend
如果你需要為某個(gè)函數(shù)的所有參數(shù)(包括this指針?biāo)傅哪莻€(gè)隱喻參數(shù))進(jìn)行類型轉(zhuǎn)換,那么這個(gè)函數(shù)必須是non-member
考慮寫出一個(gè)不拋出異常的swap函數(shù)
當(dāng)做swap時(shí),如果交換內(nèi)部的指針,效率就高了呀
以指針指向一個(gè)對(duì)象,內(nèi)含真正的數(shù)據(jù),即pimpl手法(pointer to implementation)
class WidgetImpl{ public: ... private: int a,b,c; } class Widget{ public: void swap(Wideget& other){ using std::swap;//必要的,在找不到class里的swap函數(shù)調(diào)用此函數(shù) swap(p,other.p); } private: WidgetImpl* p; } //修訂后的std::swap特化版本 namespace std{ template<> void swap<Widget>(Widget& a,Widget& b) { a.swap(b);//調(diào)用a的swap成員函數(shù) } }
這種方法和STL有一致性,因?yàn)镾TL也提供有public的成員函數(shù)和std::swap的特化版本
如果swap的默認(rèn)版本的效率你可以接受,那不需要做任何事
如果swap的默認(rèn)版本實(shí)現(xiàn)效率不足:
1、提供一個(gè)public swap成員函數(shù),讓它高效的置換兩個(gè)對(duì)象(pimpl)
2、在class的命名空間內(nèi)提供一個(gè)non-member swap,并用它調(diào)用上訴swap成員函數(shù)。
3、如果正在編寫一個(gè)class,為class特化std::swap,并用它調(diào)用你的swap成員函數(shù)。
到此這篇關(guān)于C++設(shè)計(jì)與聲明超詳細(xì)講解的文章就介紹到這了,更多相關(guān)C++設(shè)計(jì)與聲明內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Qt基礎(chǔ)開(kāi)發(fā)之Qt多線程類QThread與Qt定時(shí)器類QTimer的詳細(xì)方法與實(shí)例
這篇文章主要介紹了Qt基礎(chǔ)開(kāi)發(fā)之Qt多線程類QThread與Qt定時(shí)器類QTimer的詳細(xì)方法與實(shí)例,需要的朋友可以參考下2020-03-03C++ OpenCV實(shí)戰(zhàn)之手寫數(shù)字識(shí)別
這篇文章主要為大家詳細(xì)介紹了如何使用machine learning機(jī)器學(xué)習(xí)模塊進(jìn)行手寫數(shù)字識(shí)別功能,文中的示例代碼講解詳細(xì),感興趣的可以了解一下2022-08-08C++11智能指針中的 unique_ptr實(shí)例詳解
unique是獨(dú)特的、唯一的意思,故名思議,unique_ptr可以“獨(dú)占”地?fù)碛兴赶虻膶?duì)象,它提供一種嚴(yán)格意義上的所有權(quán)。這篇文章主要介紹了C++11智能指針中的 unique_ptr實(shí)例詳解,需要的朋友可以參考下2020-06-06C++實(shí)現(xiàn)LeetCode(206.倒置鏈表)
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(206.倒置鏈表),本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07C++實(shí)現(xiàn)飛機(jī)大戰(zhàn)游戲
這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)飛機(jī)大戰(zhàn)游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-06-06c語(yǔ)言中字符串分割函數(shù)及實(shí)現(xiàn)方法
下面小編就為大家?guī)?lái)一篇c語(yǔ)言中字符串分割函數(shù)及實(shí)現(xiàn)方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-05-05減少C++代碼編譯時(shí)間的簡(jiǎn)單方法(必看篇)
下面小編就為大家?guī)?lái)一篇減少C++代碼編譯時(shí)間的簡(jiǎn)單方法(必看篇)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-01-01