簡體   English   中英

具體類的單獨頭文件 - C ++

[英]Separate header files for concrete classes - C++

背景

我有一個抽象類,類似於

class IConverter{
    public:
    virtual void DoConvertion() = 0;
};

將有許多具體的類只是實現DoConvertion方法。

class TextConverter : public IConverter{
    public:
    virtual void DoConvertion(){
         // my code goes here
     }
};

class ImageConverter : public IConverter{
    public:
    virtual void DoConvertion(){
         // my code goes here
     }
};

這樣會有很多具體的實現。 我創建了一個頭文件,比如說CharacterConverter.h ,它有一個抽象類IConverter

由於我的具體類只實現了DoConvertion方法,是否需要為每個具體類創建單獨的頭文件? 我的意思是它需要為所有具體類創建ImageConverter.hTextConverter.h等等嗎? 所有這些頭文件都將包含與IConverter抽象類相同的代碼。

有什么想法嗎?

這不是必需的。 這基本上是一個判斷電話。

如果每個類的實現都很簡單,你可以將它們全部放在一個.h和一個.cpp中

如果實現有點長,那么為每個實現使用單獨的.h和.cpp文件可能更簡潔。

為每個類使用不同的.h / .cpp的一些優點:

  • 它將保持代碼整潔有序
  • 減少編譯工作:其中一個實現的更改不需要重新編譯所有其他實現
  • 更快的編譯時間:一些編譯器可以一次編譯多個文件,例如Visual Studio的/ MP開關。 使用多個文件,您將獲得更快的編譯時間。
  • 其他文件只能包含他們需要的內容而不是一切
  • 更快的鏈接時間:由於增量鏈接,鏈接時間將減少
  • 使用版本控制,您可以僅回顧對特定派生類的更改,而不必對大量1 .h / .cpp文件進行所有更改,以查找特定派生類中的一個更改。

你可能會得到兩種方式的答案。

我會說,對於任何簡單的轉換器,將它們全部放在一個.h / .cpp對中就足夠了,將每一個分成一對就太過分了。 我認為在這種情況下,維護大量文件與在一個文件中維護一堆方法的權衡是值得的。

復雜的轉換可能值得擁有自己的文件對。

您將需要具體類的定義來創建對象,因此您需要將這些定義放在某個.h文件中。 你把它們放在哪個文件取決於你。

對此最好的答案是更容易閱讀。 一個很長的源文件對你和其他程序員來說很難跟上。 另一方面,許多微小的(半屏幕完整)源文件同樣糟糕。

你可以考慮的東西,取決於你的設計的其余部分,是一個工廠,你的抽象類有一個靜態方法(或多個靜態方法,取決於你如何實現它)構建適當的子類並將其作為IConverter返回* 。 這樣,您可以只在頭文件中公開抽象定義,並在單個.cpp文件中包含所有具體的類定義和實現以及超類實現。 如果您的子類很大,這會變得有點笨拙,但是如果類較小,則會減少您必須管理的文件數量。

但是,正如其他人所指出的那樣,這最終是一種判斷。 唯一的性能問題與編譯有關; 更多的cpp文件可能需要(稍微)更長的時間來編譯,更多的頭文件可能會增加依賴性分析。 但是並不要求每個頭文件都有匹配的cpp和反之亦然。

根據評論,我建議這樣的結構:

IConverter.h ==> IConverter的定義
Converters.h ==>所有子類的定義
IConverter.cpp ==>包括IConverter.h和Converters.h,包含IConverter抽象功能的實現(靜態工廠方法和任何可繼承的功能)
TextConvter.cpp,ImagerConverter.cpp等等==>每個子類的單獨cpp文件,每個子類包含IConverter.h和Converters.h

這允許您僅在使用工廠和通用功能的任何客戶端中包含IConverter.h。 將所有其他定義放在單個標題中,如果它們基本相同,則可以合並。 單獨的cpp文件允許您利用Brian提到的編譯器優勢。 您可以如上所述內聯頭文件中的子類定義,但這並不能真正為您帶來任何好處。 在內聯等優化方面,您的編譯器通常比您更聰明。

創建接口類的一個要點是,客戶端可以依賴於抽象接口而不是具體實現,然后您可以自由地更改實現而不會影響客戶端。

將具體聲明放在與接口聲明相同的頭文件中會使其失敗,所以現在如果更改具體類的實現細節,則客戶端需要重新編譯。

使用工廠或函數指針可能會更好。

然而,一種特別令人討厭的方式是使用宏來聲明你的具體類。 例如:

在IConverter.h的底部包含以下宏

#define DECLARE_CONVERTER_CLASS(CLASS_NAME) \
class CLASS_NAME : public IConverter\
{ \
    public: \
    CLASS_NAME() {} \
    virtual void DoConversion(); \
}; \

然后在MyConverter1.cpp中

DECLARE_CONVERTER_CLASS(MyConverter1)

virtual void MyConverter1::DoConversion()
{
    ...
}

哎呀:-)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM