2014-01-10 66 views
1

我最近遇到一個實例,在這個實例中,我意識到我編寫的幾個類共享了很多功能。我意識到我可以將這些類推廣到具有一些模板參數的公共基礎中。問題是這些類有大約20種不同的重載構造函數,其中大多數類的功能都被實現。用我想出瞭解決方案來說明:C++ 11通過可變參數模板繼承的構造函數

template <typename T> 
class Base { 

    protected: 

    T member_; 

    public: 

    Base(int a) { /* ... */ } 

    Base(double a) { /* ... */ } 

    Base(char a) { /* ... */ } 

    Base(int a, double b, char c) { /* ... */ } 

    // etc... 

}; 

class Derived1 : public Base<int> { 

    public: 

    template <typename... Args> 
    Derived1(Args... args) : Base(args...) { } 

    // other constructors specific to Derived1 

}; 

class Derived2 : public Base<char> { 

    public: 

    template <typename... Args> 
    Derived2(Args... args) : Base(args...) { } 

    // other constructors specific to Derived2 

}; 

我這裏有幾個問題:

  1. 是否有與此相關的任何運行時性能損失? (環顧四周後,好像我應該在派生類中使用右值引用和std::forward,對吧?)
  2. 從代碼可維護性的角度來看,這是一個好主意嗎?
  3. 這種方法有什麼缺陷? (例如,其他地方的類似示例似乎正在使用explicit關鍵字。爲什麼?)
  4. 是否有更好,更標準,更安全或更可讀的方式來執行此操作?

回答

3
  1. 是的,你應該用完美轉發。如果構造函數聲明爲內聯,則性能影響爲零。

  2. 這是一個「可怕的模板」,但很容易被模板知道的人識別。取決於你的維護者,我猜?

  3. 您需要小心攔截用於派生類的複製和移動構造函數的調用,因爲您的可變參數完美轉發簽名匹配所有內容。通過enable_if正確約束通常需要比轉發構造函數本身更多的代碼。

  4. 繼承構造函數是「更好」的方法。指定該功能是爲了避免捕獲應該轉到派生類構造函數的簽名。編譯器的支持可能是不確定的:這不是最容易實現的特性,也不是最需要的特性,因此實現者在一段時間內推遲了這一點。

4

在C++ 11中,構造函數可以被繼承。

https://stackoverflow.com/a/434784/232574

+0

是否存在與繼承構造函數相關的運行時間懲罰,因爲您在跳過更多(與複製構造函數相比,與我的版本相比)?編譯器對此功能的支持如何? –

+0

沒有運行時間損失。這只是編譯器基本上將基礎構造函數轉發給派生的簡寫。查看http://stackoverflow.com/questions/9979194/what-is-constructor-inheritance獲取更多信息 –

+0

謝謝。兩個答案都很好。我現在接受了另一個,但我認爲這個問題的未來觀衆將從這裏得到兩個答案中受益。 –