網站首頁 編程語言 正文
讓接口被正確使用不易被誤用
除非有好的理由,否則應該讓你的types的行為與內置types一致,請拿ints做范本
提供行為一致的接口!
阻止誤用的辦法包括建立新類型,限制類型上的操作,束縛對象值(比如要統計年月日,限制月的大小在1-12),消除客戶的資源管理責任(智能指針)
shared_ptr支持定制型刪除器,可被用來自動解除互斥鎖等
寧以pass-by-reference-to-const替換pass-by-value
值傳遞要調用copy構造函數,釋放時要調用多次析構函數(有副本),費時
const的必要性:引用傳遞代替值傳遞時,確保不會對傳入的數據做改變
防止被切割:
class Window{
public:
virtual void display();
}
class WindowWithScrollBars:public Window{
public:
virtual void display();
}
void show(Window w){
w.display();
}
當用一個WindowWithScrollBars對象傳入show時,因為是值傳遞,會導致其特化信息被切割,變成了一個Window對象!無法多態了!
應該如下:傳進來的窗口是什么類型,w就表現出哪種特性
void show(const Window& w){
...
}
說到底,引用是指針實現出來的,引用傳遞說到底也是傳遞的指針,如果有一個對象屬于內置類型,值傳遞效率會比引用傳遞效率高一些。
值傳遞對于內置類型和STL的迭代器和函數對象來說代價不貴,其他類型還是選用const引用傳遞好!
必須返回對象時
別妄想返回reference
不是所有情況都是引用傳遞好
const A& operator*(const A& rhs){
A result(rhs);//調用構造函數
return result;
}
返回了一個result的引用,但result是一個局部變量,離開作用域就被析構了!!!
引用不能返回一個局部對象,否則一敗涂地
一個必須返回新對象的函數的做法是:就讓他返回一個新對象唄
const A operator*(const A& rhs){
A result(rhs);//調用構造函數
return A(rhs);
}
承受一個operator*構造和析構函數的代價即可
絕對不要返回一個指針或引用指向一個local stack對象(出作用域會被析構),或返回引用指向一個heap-allocated對象(無法保證合理的delete),或返回指針或引用指向一個local static對象而有可能同時需要多個這樣的對象(一個指針修改了指向對象的參數后,其他指針指向的參數也被修改了)
將成員變量聲明為private
語法一致性:成員變量不是public,用戶只能通過public里的相應函數來訪問成員變量,用戶使用時就都有一致的使用規則(全都要使用小括號等)
使用函數可以對成員變量的處理有更精確的控制,如可以編寫const函數實現只讀訪問,不加const實現讀寫訪問等
封裝性,防止成員變量被更改
假如有一個public成員變量,我們最終取消了它,所有使用它的代碼都會被破壞,假如有一個protected成員變量,我們最終取消了它,所有使用它的派生類都會被破壞。因此protected其實并不比public更加具有封裝性
說到底,選擇private就好
以non-member non-friend替換member函數
能夠訪問private成員變量的函數只有class的member函數加上friend函數,如果要在一個member函數(不只可以訪問private數據,也能取用private函數、enums、typedefs等)和一個non-member,non-friend函數做抉擇,較好封裝性的時后者。因為它并不增加能夠訪問class內private成分的函數數量
將所有便利函數放在多個頭文件內但同屬于一個命名空間,用戶可以輕松添加這一組便利函數,即可以添加更多的non-member,non-friend函數到此命名空間
參考C++標準程序庫,vector、algorithm等,導入頭文件再進行調用,即可完成很多事情
non-member
若所有參數皆需要類型轉換,請為此采用non-member函數
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);//發生了隱式轉換 得益于之前沒有將構造函數聲明為explicit
result=2.operator*(onehalf);
2沒有相應的class,沒有operator*成員函數,當然無法執行
結論為:只有當參數被列于參數列內,這個參數才是隱式轉換的合格參與者
改變做法為將operator*變成non-member函數,允許編譯器在每個實參上執行隱式轉換
operator*是否應該成為class的一個friend函數呢?否定的,因為operator*完全可以借用Rational的public接口完成任務,這告訴我們:member函數的反面是non-member,而不是friend
如果你需要為某個函數的所有參數(包括this指針所指的那個隱喻參數)進行類型轉換,那么這個函數必須是non-member
考慮寫出一個不拋出異常的swap函數
當做swap時,如果交換內部的指針,效率就高了呀
以指針指向一個對象,內含真正的數據,即pimpl手法(pointer to implementation)
class WidgetImpl{
public:
...
private:
int a,b,c;
}
class Widget{
public:
void swap(Wideget& other){
using std::swap;//必要的,在找不到class里的swap函數調用此函數
swap(p,other.p);
}
private:
WidgetImpl* p;
}
//修訂后的std::swap特化版本
namespace std{
template<>
void swap<Widget>(Widget& a,Widget& b)
{
a.swap(b);//調用a的swap成員函數
}
}
這種方法和STL有一致性,因為STL也提供有public的成員函數和std::swap的特化版本
如果swap的默認版本的效率你可以接受,那不需要做任何事
如果swap的默認版本實現效率不足:
1、提供一個public swap成員函數,讓它高效的置換兩個對象(pimpl)
2、在class的命名空間內提供一個non-member swap,并用它調用上訴swap成員函數。
3、如果正在編寫一個class,為class特化std::swap,并用它調用你的swap成員函數。
原文鏈接:https://blog.csdn.net/RolleX/article/details/126982795
相關推薦
- 2022-08-01 Go語言上下文context底層原理_Golang
- 2021-11-18 C/C++?Qt?TableDelegate?自定義代理組件使用詳解_C 語言
- 2022-08-12 Go單元測試對GORM進行Mock測試_Golang
- 2022-11-09 Go語言數據結構之二叉樹可視化詳解_Golang
- 2023-10-14 c/c++--字節對齊(byte alignment)
- 2022-06-16 golang默認Logger日志庫在項目中使用Zap日志庫_Golang
- 2022-07-21 Linux上源碼包安裝nginx及yum 安裝nginx
- 2022-04-12 jieba.posseg.cut分詞結果與jieba.cut不一致
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支