2014-02-24 65 views
2

在C++經常可以看到的東西,如:將C++類成員一致地定義爲唯一指針;

類C的部首

//== C.h ==// 
#pragma once 
#include "B.h" 

class C 
{ 
    B b; 
}; 

類B的部首

//== B.h ==// 
#pragma once 
#include "A.h" 

class B 
{ 
    A a; 
}; 

類的首部A

//== A.h ==// 
#pragma once 

class A 
{ 

}; 

由於C.h包括B.h,和B.h包括A.h; C.h最終知道關於A.h的實現細節。在這種情況下,標題只包含三個深度級別,但在包含一個標題的大型項目中可以快速導入包含數百個額外標題。也導致編譯時間過長。

在C++ 11 I可以宣佈標題如下:

//== C.h ==// 
#pragma once 
#include <memory> 

// proto 
class B; 

class C 
{ 
    std::unique_ptr<B> b; 
}; 

類B的部首

//== B.h ==// 
#pragma once 
#include <memory> 

// proto 
class A; 

class B 
{ 
    std::unique_ptr<A> a; 
}; 

部首類的

//== A.h ==// 
#pragma once 

class A 
{ 

}; 

C類的報頭

Wh用智能指針替換所有成員(類,結構體),我可以包含C.h而不必知道類B的實現。每個cpp文件現在只需知道它的成員,而不必知道它的成員的內存佈局。

我的問題是:

  • 是好設計實踐(一個好主意),以取代所有的類成員,那要麼是類和結構,具有獨特的指針?他們的額外親或者是否?
+2

這與pimpl成語相似。缺點是每次你想訪問成員時都會有間接的問題,而且你的班級佈局現在已經在內存中有效地分散了。 – Simple

+0

不完全。 pImpl將一個類拆分爲私有和公共部分,並允許通過公共接口訪問私有實現。它也是一個編譯防火牆,但有些不同。 – Enigma

+0

這甚至不是一個很好的代碼。如果完整的類聲明不存在,您將無法使用默認的刪除器instanciate unique_ptr,因爲它會對轉發的類型調用delete,這是未定義的行爲。我贊同@Simple,你提出的只不過是Pimpl。 – galop1n

回答

4

直接數據成員支持複製默認情況下,如果他們的類型支持複製。而且效率最高。如果人們認爲在更短的構建時間內進行交易是值得的,那麼爲什麼要使用C++呢?爲什麼不使用C++呢?那麼就使用最大限度利用這種權衡的語言,比如Java或C#。

換句話說,它似乎是一個不好的想法。

爲了縮短構建時間,同時仍然使用C++,請考慮更快的機器或構建服務器停放。

1

用指針替換所有成員不是一個好主意,因爲它會增加一個額外的解引用層。直接成員實際上是在包含對象內分配的,因此訪問它只需要包含對象位置的固定偏移量。

如果隱藏指針後面的所有內容,您需要訪問指針成員,然後取消引用訪問數據的指針(這將在內存中的其他位置)。這是個人基礎上的微不足道的開銷,但如果原則在整個計劃中得到擴展,它很快就會加起來。

要牢記的另一個問題是可維護性。如果您通過指針存儲所有內容,則需要手動包含適當的構造和複製。這可能會導致大型項目出現各種問題,因爲這會增加程序員錯誤的可能性。相比之下,如果您使用直接成員,編譯器會自動執行很多操作。

另一個值得關注的方法是PIMPL設計模式(私有實現或指向實現的指針)。它本質上是一種在源文件中隱藏類的私有細節的方式,以減少標頭依賴性。