2017-02-09 105 views
6

通常情況下,如果我有一個FooBar,我會做這樣的事情:是否可以創建一個可用於創建任何類的「新」實例的泛型方法或類?

Foo* foo = new Foo(); 

Bar* bar = new Bar(2,3,5); 

是否有使用模板或宏的方式,我可以構建一個功能,這樣我可以這樣做:

Foo* foo = MyAwesomeFunc(Foo); 
Bar* bar = MyAwesomeFunc(Bar,2,3,5); 

MyAwesomeFunc的實際方法簽名對我來說並不重要。

FooBar不需要以任何可能的方式有關,並可能有完全不同的構造。此外,我可能要在將來支持任意數量的類,而不必實際修改代碼MyAwesomeFunc

這可能嗎?一個簡單的辦法是同時擁有Foo和一些類型Bar繼承,說Baz,並有重載方法返回一個Baz,你投回到FooBar ...

Baz* MyAwesomeFunc(){ 
    return new Foo(); 
} 

Baz* MyAwesomeFunc(int a,int b,int c){ 
    return new Bar(a,b,c); 
} 

但這裏的問題是你會寫:支持

  • 和各種構造簽名的

    1. 爲每個類的方法。

    的目標,是寫一個類,方法,或宏,在這裏我們可以 調用一個函數(傳遞的任何參數),但調用傳入的對象右側 構造。這可能嗎 ?

    這個問題的目的是簡單地探討是否有可能在C++中做這樣的事情。請不要提出共同的指針,獨特的指針,使用新的缺陷,因爲這是脫離主題。

    編輯:我想只使用STL,並避免使用像升壓....

  • +1

    查看'boost :: factory' – Ari0nhh

    +0

    @Ar i0nhh謝謝阿里 - 任何方式輕鬆地做到這一點,而無需使用Boost? –

    +3

    Pre C++ 11,「Perfect Forwarding」和「Variadic Templates」不存在。 'Boost'爲社區提供了製作愚蠢強大代碼的工具,'boost :: factory'是事實上的工廠,它被完美的轉發和可變模板所取代。 – Gambit

    回答

    8

    由於C++ 11你可以用variadic templateperfect forward做到這一點。例如。編寫一個模板函數,它完美地將其參數轉發給模板參數指定的類型的對象的構造函數。

    template <typename T, typename... Ts> 
    T* MyAwesomeFunc(Ts&&... params){ 
        return new T(std::forward<Ts>(params)...); 
    } 
    

    然後用它作爲

    Foo* foo = MyAwesomeFunc<Foo>(); 
    Bar* bar = MyAwesomeFunc<Bar>(2,3,5); 
    
    +1

    如果您嘗試創建一個Bar,但沒有所有必需的參數,會發生什麼情況? –

    +1

    您可以使用'type_traits'中的'std :: is_constructible'。看到我的答案。 – Gambit

    +5

    @John,編譯器錯誤。它從外部看起來並不完美,但是有辦法解決這個問題(概念和模擬)。 – chris

    8

    是的,你可以使用模板和C++ 11的 「完美轉發」:

    #include <type_traits> 
    #include <utility> 
    
    template<typename T, typename... Args> 
    T* createNew(Args&&... args) 
    { 
        static_assert(std::is_constructible<T, Args...>::value, "T is not constructible with these arguments"); 
        return new T(std::forward<Args>(args)...); 
    } 
    

    或者,你可以看看C++ 11的std::make_unique和「智能指針」What is a smart pointer and when should I use one?

    +0

    如果會出現編譯器錯誤,那爲什麼要用std :: is_constructible? –

    +4

    因爲你可以設置自己的消息,它不會在可怕的編譯錯誤中丟失。 – Gambit

    相關問題