如何在共享指针中使用模板类的前向声明(在C ++中)

时间:2016-12-04 23:55:32

标签: c++ c++11 templates shared-ptr

我在 Base.h

中定义了基类Base
class Base
{ /* ... */ };

来自Child的类模板Base,在 Child.h 中定义:

#include "Base.h"

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

现在我想在Base类中创建一些工厂方法,它应该将std::shared_ptr返回到Child类。为了避免循环依赖,我尝试使用前向声明。所以 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:期待'&gt;'终止template-argument-list,找到'&lt;'“

这是否有可能实现我想要实现的目标? 如果没有,这种方法是否有任何变通方法/最佳实践?

修改: 我想将工厂方法放入Base类而不是Child的原因如下。当我将工厂放入Child时,我需要像这样调用工厂方法:

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

但是,我想在此调用中省略模板类型<int>,因此:

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

1 个答案:

答案 0 :(得分:3)

首先,您声明了一个类,但您定义的Child实际上是一个模板。声明类模板的正确方法是:

template <class T>
class Child;

然而,单独一个正确的前瞻性声明对你没有帮助。 CreateChildInt::CreateChildInt的实现必须知道Child的完整定义,因为它创建了它的实例。你也不能在Child之前定义Base,因为继承也取决于完整的定义,所以你最终会得到一个cicrular依赖。

解决方案:转发声明Child,然后定义Base但不定义Base::CreateChildInt内联,然后定义Child,最后定义Base::CreateChildInt

PS。从OOP的角度来看,我发现基类成员函数的实现依赖于子类。我建议你考虑重新设计你的方法。