读书笔记_Effective_C++_条款三十一:将文件间的编译依存关系降至最低(第二部分)...
下面再來看書,去理解書上說的Handler classes就簡單多了,我們大概過一下。
假設我們要寫一個Person類,如下:
1 class Person 2 { 3 private: 4 string name; 5 MyDate birthday; 6 MyAddress address; 7 8 public: 9 // fallows functions 10 // ... 11 };這個Person類里面包含有人的名字,人的生日以及地址,還有一些沒有列出來的方法。注意到這里用到了string(它不是一個class,只是一個typedef,大多數情況下,我們認為它不會有任何改變),以及自定義的類MyDate與MyAddress,一種常見的做法是采用include頭文件,像這樣:
1 #include <string> 2 #include "MyDate.h" 3 #include "MyAddress.h"在MyDate.h里面寫好日期類相關的成員變量與方法,而在MyAddress.h里面寫好地址類相關的成員變量與方法。但如果此后要往MyDate類或者MyAddresss類添加成員變量,那么不僅僅所有用到MyDate或者MyAddress對象的文件需要重新編譯,而且所有用到Person對象的文件也需要重編譯,一個小改動竟然會牽涉到這么多的地方!
?
可以把問題歸結為“C++并沒有把將接口從實現中分離這件事做好”,因為包含頭文件的做法很直觀很方便,用的人也很普遍,而C++并沒有對這種做法加以限制。
如果要把編譯的依賴性降低,就要換一種思路來處理,不能出現定義式,只能出現聲明式,代價是增加代碼的復雜度以及性能上的一些損失。
?
書上提到了兩種方法,第一種是采用Handler Classes(用指針指向真正實現的方法),第二種是Interface Classes(抽象基類)。
?
對于第一種Handler Class,一句話,就是.h里面不包含類的自定義頭文件,用“class 類名”的聲明方式進行代替(也要把相應的成員變量替換成指針或引用的形式),在.cpp文件里面包含類的自定義頭文件去實現具體的方法。改造之后的程序看起來是這樣子的:
1 // Person.h 2 #include <string> 3 using namespace std; 4 5 class PersonImp; 6 7 class Person 8 { 9 private: 10 //string Name; 11 //MyDate Birthday; 12 //MyAddress Address; 13 PersonImp* MemberImp; 14 15 public: 16 string GetName() const; 17 string GetBirthday() const; 18 string GetAddress() const; 19 // follows functions 20 // ... 21 }; 1 // Person.cpp 2 #include "PersonImp.h" 3 #include "Person.h" 4 5 string Person::GetName() const 6 { 7 return MemberImp->GetName(); 8 } 9 string Person::GetBirthday() const 10 { 11 return MemberImp->GetName(); 12 } 13 string Person::GetAddress() const 14 { 15 return MemberImp->GetAddress(); 16 } 1 // PersonImp.h 2 #ifndef PersonImp_H 3 #define PersonImp_H 4 5 #include <string> 6 #include "MyAddress.h" 7 #include "MyDate.h" 8 using namespace std; 9 10 class PersonImp 11 { 12 private: 13 string Name; 14 MyAddress Address; 15 MyDate Birthday; 16 17 public: 18 string GetName() const 19 { 20 return Name; 21 } 22 23 string GetAddress() const 24 { 25 return Address.ToString(); 26 } 27 28 string GetBirthday() const 29 { 30 return Birthday.ToString(); 31 } 32 }; 33 34 #endif /* PersonImp_H */ 1 // MyDate.h 2 #ifndef MY_DATE_H 3 #define MY_DATE_H 4 5 #include <string> 6 using namespace std; 7 8 class MyDate 9 { 10 private: 11 int Year; 12 int Month; 13 int DayOfMonth; 14 15 public: 16 string ToString() const; 17 } 18 #endif /* MY_DATE_H */ 1 // MyAddress.h 2 #ifndef MY_ADDRESS_H 3 #define MY_ADDRESS_H 4 5 #include <string> 6 using namespace std; 7 8 class MyAddress 9 { 10 private: 11 string Country; 12 string Province; 13 string City; 14 string Street; 15 16 public: 17 string ToString() const; 18 }; 19 20 #endif /* MY_ADDRESS_H */這里有一點要說一下,在Person.h里面并沒有使用MyDate*和MyAddress*,而是用了PersonImp*,由PersonImp里面包含MyDate與MyAddress,這樣做的好處就是方便統一化管理,它要求PersonImp里面的方法與Person的方法是一致的。以后Person添加成員變量,可以直接在PersonImp中進行添加了,從而起到了隔離和隱藏的作用,因為客戶端代碼大量使用的將是Person,而不必關心PersonImp,用于幕后實現的PersonImp只面向于軟件開發者而不是使用者。
書上是用shared_ptr來管理PersonImp的,使資源管理上更加科學與合理。
另外,書上也提倡把class x; class xx; class xxx;的聲明放至一個名為”xxxfwd.h”的頭文件里,比如”datefwd.h”,這個頭文件里面只有聲明式,而沒有具體的類細節。也就是說,對于某個類,比如MyDate,應該分出三個文件,一個是datefwd.h,里面是一些用到的外來的class聲明式;一個是MyDate.h里面是MyDate類的結構聲明;一個是MyDate.cpp,它與MyDate.h配對,給出具體的實現細節。
?
?
?
轉載于:https://www.cnblogs.com/jerry19880126/p/3551839.html
總結
以上是生活随笔為你收集整理的读书笔记_Effective_C++_条款三十一:将文件间的编译依存关系降至最低(第二部分)...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 支付系统灰度发布原理图
- 下一篇: 如何修改ant-input的高度_如何利