2016-03-15 94 views
0

創建由其他類組成的類時,是否值得通過使用指針而不是值來減少依賴關係(從而減少編譯時間)?應該使用指針來減少頭依賴關係嗎?

例如,以下使用值。

// ThingId.hpp 
class ThingId 
{ 
    // ... 
}; 

// Thing.hpp 
#include "ThingId.hpp" 
class Thing 
{ 
public: 
    Thing(const ThingId& thingId); 
private: 
    ThingId thingId_; 
}; 

// Thing.cpp 
#include "Thing.hpp" 
Thing::Thing(const ThingId& thingId) : 
    thingId_(thingId) {} 

但是,下面的修改版本使用指針。

// ThingId.hpp 
class ThingId 
{ 
    // ... 
}; 

// Thing.hpp 
class ThingId; 
class Thing 
{ 
public: 
    Thing(const ThingId& thingId); 
private: 
    ThingId* thingId_; 
}; 

// Thing.cpp 
#include "ThingId.hpp" 
#include "Thing.hpp" 
Thing::Thing(const ThingId& thingId) : 
    thingId_(new ThingId(thingId)) {} 

我讀過,推薦這樣的做法,但如果你有大量的指針,就會有大量的new調用,我想會是緩慢的一個職位。

+0

「是否值得通過使用指針而不是值來減少依賴關係(從而編譯時間)?」 - 我看不到如何使用指針「減少依賴關係」 - 以及它與編譯時間的關係。 – Dai

+0

沒有任何關於需要「新」調用的指針。我可以編寫一堆代碼,並在各處指向指針,而不是一個'new'調用。 –

+0

@Dai:你可以轉發聲明pointee類型,而不是'#include'這個類型完全定義的整個頭文件。 –

回答

2

如果您的程序不能保證動態分配,請不要爲了項目組織而介紹它。那絕對會是一個虛假的經濟。

你真正想要做的是試圖完全減少類間依賴的數量。

但是,只要你的耦合是明智的,樹狀的,不要太擔心。如果你正在使用預編譯頭文件(你是,對吧?),那麼這對編譯時間來說都不重要。

+0

我認爲這個問題也是很大的依賴樹。小的,可能不相關的某些標題變化可能會導致大部分項目重新編譯。對於大型項目來說,這可能會令人望而卻步,比如防止夜間搭建和測試。當我在漢堡申請Star Division(Star Office,後來的OpenOffice)工作時,這是一個問題:「如果你想添加一個虛擬函數到一個多態類而不重新編譯所有使用這個類的文件;你在哪裏放置類聲明中的新函數?「 (最後,因爲VTable中所有早期的偏移量都沒有改變)。 –

+0

「你真正想做的是試圖完全減少類間依賴的數量。」任何有關這方面的參考資料? – magnus

+0

@ user1420752:任何有關軟件設計的好書,真的 –

3

這是大多數人稱之爲皮姆普成語(http://c2.com/cgi/wiki?PimplIdiom)。

簡單的答案

我高度懷疑,你沒有這個良好的使用情況,並應該避免不惜一切代價。

我的經驗

主要方式,平普爾曾經對我有用的是使一個實現細節保密。它實現了這一點,因爲你不需要包含你的依賴關係的頭文件,但可以簡單地轉發聲明它們的類型。

如果你想提供一個SDK的人,它使用引擎蓋下的一些Boost庫的代碼,但是你想要的後來換是出於對其他一些庫的選項,而不產生任何問題對於你的SDK的消費者來說,Pimpl可以有很大的意義。

它還有助於在實現上創建一個門面,以便您可以控制整個公開接口,而不是暴露您隱式依賴的庫,從而控制您無法控制的整個接口並可能改變,可能暴露過多,可能難以使用等。

+0

我在這裏看不到Pimpl的證據。 –