在C++和Objective-C中,我養成了向前聲明不需要在頭文件中定義的必要類的習慣,然後根據需要導入在源文件中定義這些類的頭文件。前向聲明的缺點?
有沒有這種情況下,這不是一個好主意? (我知道前向聲明的一大缺點是不完整類型的可用性有限。對於這個問題,假設在頭文件中我只需要使用前面聲明的類作爲不完整類型)。
在C++和Objective-C中,我養成了向前聲明不需要在頭文件中定義的必要類的習慣,然後根據需要導入在源文件中定義這些類的頭文件。前向聲明的缺點?
有沒有這種情況下,這不是一個好主意? (我知道前向聲明的一大缺點是不完整類型的可用性有限。對於這個問題,假設在頭文件中我只需要使用前面聲明的類作爲不完整類型)。
有時候,你可以改變程序的語義微妙而不引發任何錯誤
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
一個缺點可能是缺乏信息隱藏/封裝。
我更喜歡擁有最小的頭文件。這意味着我沒有義務繼續支持如此多的功能。如果我想改變某些事情,而且公衆頭上還沒有公開的內容,那麼我可以更好地在內部將它改爲全班而不影響其他人。
編輯:
盧克要求的例子,所以這裏亞去:
假設你有一個叫Car
類。而且,你建立它的唯一方法是從A點到B點。我個人而言,我寧願將我的頭文件保存爲:名爲Car
的類和名爲Drive
的方法。從你的問題(「我所能做的所有類」)的角度來看,我希望在頭文件中找到像「DieselEngine」,「PetrolEngine」,「HybidEngine」等類。與此相關的問題是,其他人從事你的項目(或者你,隨着時間的推移)開始使用那些暴露的類。現在,兩年後,你決定「Hrm ... PetrolEngine類真的給我造成了問題,我想我只是將它刪除,並用HybridEngine代替它,完全在我的Car類中」 - 現在,PetrolEngine包含在其他100個文件中,因爲你不明白的原因 - 現在你不得不保留PetrolEngine(和以前一樣工作),對於那些在某些人中使用它的人來說,你並不確定 - 因爲你沒有一份紮實的工作「契約」,因爲你首先需要這個班級。這是你真正想要完成的實現細節 - 建造一輛汽車。
編輯討論有關信息隱藏評論:
如果你正在做的是嚴格的前瞻性聲明的類/結構的名字 - 好吧,我想我會問「爲什麼」了。如果我是頭文件和類的消費者,並且我實際上無法對該類執行任何操作(並且它不作爲主類的API的參數或返回類型公開),那麼爲什麼要公開它?
如果你使用它編譯時對不透明數據結構進行安全檢查 - 很好 - 那是一回事。但是,你的措辭使你的問題聽起來像聽起來似乎是所有的在頭文件中。據我所知,
我不確定我是否知道你的意思。你能舉個例子嗎? – Luke
這種技術不會增強信息隱藏嗎?前向聲明中的信息少於完整聲明中的信息。 –
您能否解釋前向聲明如何破壞封裝?在我看來,只提供類名隱藏了比提供完整定義更多的信息。 –
沒有。你已經講過的唯一缺點是使用不完整的類型。既然你說沒有任何需要完全定義類型的用法,我猜你沒問題。
如果您不需要標題中的類的完整定義,則前向聲明比全文件包含更受歡迎。我能想到的唯一缺點是已經作爲@Stephen Darlington的評論發佈,如果可以的話,我會給10個upvotes。 :)
一個缺點是前向聲明類型中潛在的內存泄漏。有關更多詳細信息,請參閱this question。在這種情況下,Microsoft編譯器問題warning C4150: deletion of pointer to incomplete type 'SomeType'; no destructor called
。
真正的編譯器沒有問題。 –
前向聲明可以應用於很多事情:類,函數,全局變量/常量(使用extern
)和C++ 11中的枚舉。
據我所知,主要的缺點是冗餘,因爲冗餘引入了更多的錯誤範圍,但是這取決於你前面聲明的內容有很大不同。
如果你有一個類的前向聲明錯誤,一個全局或枚舉,編譯器應該選擇它(是啊!)。
如果你的函數聲明有錯誤,那麼在C++中,你只是簡單地創建了一個重載(oups!)。
因此,我會說,轉發聲明類,全局變量或枚舉並沒有真正的缺點;但是在功能方面,如果你堅持使用#include
,那麼你總是可以創建標題組合相關函數,以避免創建太多文件。
這可能主要是一個可讀性問題,您的同事將不得不繼續您的編碼工作。
在完整版本中喝咖啡的機會較少? –