【问题标题】:How to use forward declarations for a template class in a shared pointer (in C++)如何在共享指针中对模板类使用前向声明(在 C++ 中)
【发布时间】:2017-04-19 07:27:42
【问题描述】:

我在 Base.h 中定义了一个基类 Base

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

还有一个派生自Base的类模板Child,在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:期望 '>' 终止模板参数列表,发现 '

那么这甚至可能是我想要实现的目标吗?
如果没有,这种方法是否有任何解决方法/最佳实践?

编辑: 我为什么要将工厂方法放入Base类而不是Child的原因如下。当我将工厂放入Child 时,我需要像这样调用工厂方法:

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

但是,我想在此调用中省略模板类型 &lt;int&gt;,因此:

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

【问题讨论】:

  • 你需要template &lt;typename&gt; class Child;
  • 为什么这个工厂函数是Base的一部分?通常,OO 基类不应该知道他们的孩子。
  • @Matthias 我不会把它放在任何一个类中。反正是static;为什么不把它放在外面?
  • 天哪!我使用 Java 的时间太长了,所以我什至没有想过在类之外创建一个普通函数的想法。就是这样,谢谢!

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


【解决方案1】:

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

template <class T>
class Child;

但是,仅靠正确的前向声明并不能帮助您。 CreateChildInt::CreateChildInt 的实现必须知道Child 的完整定义,因为它创建了它的一个实例。你也不能在Base 之前定义Child,因为继承也依赖于完整的定义,所以你最终会得到一个循环依赖。

解决方案:前向声明Child,然后定义Base但不定义Base::CreateChildInt inline,然后定义Child,最后定义Base::CreateChildInt


附言。我发现从 OOP 的角度来看,基类成员函数的实现取决于子类是可疑的。我建议您考虑重新设计您的方法。

【讨论】:

  • 我已经更新了我原来的问题,以更好地解释我想要实现的目标,以及为什么要将工厂方法放入 Base 类中。
  • @Matthias 您有强烈反对将工厂函数放入子类的论据,但您有任何反对将工厂函数放入基类而不是外部的论据吗?
  • 你是对的,来自Java我没有想过将函数放在类之外的想法:)
猜你喜欢
  • 1970-01-01
  • 2011-09-14
  • 2014-12-01
  • 1970-01-01
  • 2018-05-26
  • 2017-04-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多