作者littleshan (我要加入劍道社!)
看板C_and_CPP
標題Re: [問題] 引入標頭檔多次(在不同namespace)
時間Sun May 26 00:30:39 2013
※ 引述《CCWck (幹嘛要暱稱)》之銘言:
: 現在原PO想要 只include A的時候 error 有AB的時候正常
: 或許可以考慮改CD的include的方式
: 在A中 include B
: 在B中 #ifndef FILE_B
: #define FILE_B
: #endif
: 在CD中 先include B
: #ifdef FILE_B
: include A
: #endif
: 如果這樣寫 當你CDE沒有先include B 的話 A也不會被include
: 應該就會造成error
你完全沒搞懂原po的目的是什麼
今天 A depends on B,所以 #include A 會自動有 #include B 的效果
在寫 C 或 D 的時候這種情況會造成誤解
一方面是你會以為 A 同時提供了 B 的功能
另一方面這是應該被隱藏的實作細節
在寫 CD 時如果假設 A depends on B,有可能會寫出過份耦合的設計
導致日後 A 更改實作時,連同 CD 也要一起更改
依照你的方法,寫 #include A 之前要先 #ifdef FILE_B
表示寫 CD 的時候要先知道 A depends on B 這項應該被隱藏的資訊
完全和我們的目的相反
更何況日後若 A 更改實作,變成 depends on Z
豈不要把 CD 裡面的 #ifdef FILE_B 改成 #ifdef FILE_Z
正確做法是使用 pimpl
A 不再 include B,而是把資訊做如下的包裝:
A.h:
#ifndef FILE_A
#define FILE_A
struct A_Impl; // forward declaration
class A {
public:
// member functions for A
private:
A_Impl* pimpl;
};
#endif
A.cpp:
#include "A.h"
#include "B.h"
struct A_Impl {
B member;
};
pimpl 的原理是把 A 用到的成員全部封裝在另一個 struct 中,
並只用 pointer 指向它。
這個 struct 的內容則是寫在 A.cpp 裡面,因此 C 或 D 都看不到。
即使修改過 A 的實作細節,也僅需重編 A.cpp 即可,
不會動到 CD
如果你的 A 在介面上就已經 depends on B,比如說某個函式參數是 B
這種情況表示 A 和 B 無法獨立成兩個模組
你也沒辦法在不動到 CD 的情況下把 A 改成 depends on Z
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 202.39.238.242
→ hilorrk:pimpl idiom 是正解,但是我覺得更實用的地方是減少 05/26 02:18
→ hilorrk:compilation time...為了隱藏細節而做的反而少見?(也是因 05/26 02:18
→ hilorrk:為我的經驗很少,看的 code base 不夠多啦XD 05/26 02:19
→ legnaleurc:library 或 framework 的介面都會用 pimpl 處理吧 05/26 12:44
推 suhorng:喔喔!!! 原來如此 (看中文的說明比看英文資料方便太多了阿 05/27 23:18
→ suhorng:Q_____Q) 這樣就可以隱藏起來了 05/27 23:19
→ suhorng:謝謝l大 05/27 23:20
推 cwahbong:還有一種常拿來做比較的是 pure virtual class ,同樣也 05/28 11:02
→ cwahbong:可以把相依性關在實作裡面 05/28 11:02