2016-12-04 95 views
4

我在Base.h定義的基類Base如何在共享指針使用正聲明爲模板類(在C++)

class Base 
{ /* ... */ }; 

和從Base派生的類模板ChildChild.h定義:

#include "Base.h" 

template <class T> 
class Child : public Base 
{ /* ... */ }; 

現在我想創建Base內的一些工廠方法類,該類應返回std::shared_ptrChild類。爲了避免循環依賴,我嘗試使用前向聲明。所以Base.h現在看起來是這樣的:

class Child; // new forward declaration 

class Base 
{ 
    /* ... */ 

    // new factory method 
    static std::shared_ptr<Base> CreateChildInt(int i = 0) 
    { 
     return std::make_shared<Child<int>>(i); 
    } 
}; 

然而,CreateChildInt()定義導致以下編譯器錯誤:

「錯誤C2947:期待 '>' 終止模板argument- list,found'<''

那麼這甚至可能是我想要實現的嗎?
如果沒有,這種方法是否有任何解決方法/最佳實踐?

編輯: 原因爲什麼我希望把工廠方法爲Base類,而不是Child如下。當我把工廠變成Child我需要調用工廠方法是這樣的:

std::shared_ptr<Base> p = Child<int>::CreateChildInt(3); 

不過,我想省略模板類型<int>在這個調用,因此:

std::shared_ptr<Base> p = Base::CreateChildInt(3); 
+0

您需要'template class Child;'。 –

+0

爲什麼這個工廠是'Base'的一部分?通常OO基礎班不應該知道他們的孩子。 – melpomene

+2

@Matthias我不會把它放在任何一堂課。無論如何它都是靜態的;爲什麼不把它放在外面? – melpomene

回答

3

首先,你宣佈了一個類,但你定義的Child實際上是一個模板。聲明一個類模板正確的方法是:

template <class T> 
class Child; 

然而,僅僅一個正確的向前聲明不會幫你。 CreateChildInt::CreateChildInt的實現必須知道Child的完整定義,因爲它創建了它的一個實例。你也不能在Base之前定義Child,因爲繼承也取決於完整的定義,所以你最終會得到一個cicrular依賴。

解決方案:轉發聲明Child,然後定義Base但沒有定義Base::CreateChildInt內聯,然後定義Child,最後確定Base::CreateChildInt


PS。我發現從OOP的角度來看,基類成員函數的實現依賴於子類。我建議你考慮重新設計你的方法。

+0

我已經更新了我的原始問題,以更好地解釋我想實現的目標,以及爲什麼我要將工廠方法放入'Base'類。 – Matthias

+2

@Matthias你有反對將工廠函數放入子類的強烈爭論,但是你有沒有將工廠函數放入基類而不是外部的任何參數? – user2079303

+0

你是對的,來自Java我還沒有想過把這個功能放在課堂外的想法:) – Matthias