2011-11-02 146 views
10

在C++和Objective-C中,我養成了向前聲明不需要在頭文件中定義的必要類的習慣,然後根據需要導入在源文件中定義這些類的頭文件。前向聲明的缺點?

有沒有這種情況下,這不是一個好主意? (我知道前向聲明的一大缺點是不完整類型的可用性有限。對於這個問題,假設在頭文件中我只需要使用前面聲明的類作爲不完整類型)。

+17

在完整版本中喝咖啡的機會較少? –

回答

6

有時候,你可以改變程序的語義微妙而不引發任何錯誤

class Foo; 

template < typename T> 
struct Trait 
{ 
    static const int MY_TYPE = -1; 
}; 

// Lets say this is Foo.h 
//class Foo 
//{ 
//}; 
//template<> 
//struct Trait<Foo> 
//{ 
// static const int MY_TYPE = 1; 
//}; 

void TestFunction(Foo& f) 
{ 
    std::cout << Trait<Foo>::MY_TYPE << std::endl; 
} 

考慮上面的代碼和註釋掉的代碼住在一個頭。如果包含標題TestFunction將打印1,否則-1

+0

+1 ..可能比我的評論更加適用,因爲我知道我現在知道關於OP的思維過程。 – Steve

+0

有趣的東西。這是我很好奇的事情。 – Luke

3

一個缺點可能是缺乏信息隱藏/封裝。

我更喜歡擁有最小的頭文件。這意味着我沒有義務繼續支持如此多的功能。如果我想改變某些事情,而且公衆頭上還沒有公開的內容,那麼我可以更好地在內部將它改爲全班而不影響其他人。

編輯:

盧克要求的例子,所以這裏亞去:

假設你有一個叫Car類。而且,你建立它的唯一方法是從A點到B點。我個人而言,我寧願將我的頭文件保存爲:名爲Car的類和名爲Drive的方法。從你的問題(「我所能做的所有類」)的角度來看,我希望在頭文件中找到像「DieselEngine」,「PetrolEngine」,「HybidEngine」等類。與此相關的問題是,其他人從事你的項目(或者你,隨着時間的推移)開始使用那些暴露的類。現在,兩年後,你決定「Hrm ... PetrolEngine類真的給我造成了問題,我想我只是將它刪除,並用HybridEngine代替它,完全在我的Car類中」 - 現在,PetrolEngine包含在其他100個文件中,因爲你不明白的原因 - 現在你不得不保留PetrolEngine(和以前一樣工作),對於那些在某些人中使用它的人來說,你並不確定 - 因爲你沒有一份紮實的工作「契約」,因爲你首先需要這個班級。這是你真正想要完成的實現細節 - 建造一輛汽車。

編輯討論有關信息隱藏評論:

如果你正在做的是嚴格的前瞻性聲明的類/結構的名字 - 好吧,我想我會問「爲什麼」了。如果我是頭文件和類的消費者,並且我實際上無法對該類執行任何操作(並且它不作爲主類的API的參數或返回類型公開),那麼爲什麼要公開它?

如果你使用它編譯時對不透明數據結構進行安全檢查 - 很好 - 那是一回事。但是,你的措辭使你的問題聽起來像聽起來似乎是所有的在頭文件中。據我所知,

+0

我不確定我是否知道你的意思。你能舉個例子嗎? – Luke

+4

這種技術不會增強信息隱藏嗎?前向聲明中的信息少於完整聲明中的信息。 –

+2

您能否解釋前向聲明如何破壞封裝?在我看來,只提供類名隱藏了比提供完整定義更多的信息。 –

0

沒有。你已經講過的唯一缺點是使用不完整的類型。既然你說沒有任何需要完全定義類型的用法,我猜你沒問題。

0

如果您不需要標題中的類的完整定義,則前向聲明比全文件包含更受歡迎。我能想到的唯一缺點是已經作爲@Stephen Darlington的評論發佈,如果可以的話,我會給10個upvotes。 :)

0

一個缺點是前向聲明類型中潛在的內存泄漏。有關更多詳細信息,請參閱this question。在這種情況下,Microsoft編譯器問題warning C4150: deletion of pointer to incomplete type 'SomeType'; no destructor called

+2

真正的編譯器沒有問題。 –

2

前向聲明可以應用於很多事情:類,函數,全局變量/常量(使用extern)和C++ 11中的枚舉。

據我所知,主要的缺點是冗餘,因爲冗餘引入了更多的錯誤範圍,但是這取決於你前面聲明的內容有很大不同。

如果你有一個類的前向聲明錯誤,一個全局或枚舉,編譯器應該選擇它(是啊!)。

如果你的函數聲明有錯誤,那麼在C++中,你只是簡單地創建了一個重載(oups!)。

因此,我會說,轉發聲明類,全局變量或枚舉並沒有真正的缺點;但是在功能方面,如果你堅持使用#include,那麼你總是可以創建標題組合相關函數,以避免創建太多文件。

0

這可能主要是一個可讀性問題,您的同事將不得不繼續您的編碼工作。