2016-12-04 97 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