c++ - 模板子类的工厂

标签 c++ c++11 templates factory

<分区>

我正在尝试使用类继承和工厂方法。

基本结构是我有一个基类Base,和一个派生类Child

方法 ChildFactory 允许选择 Child 的不同实现,它们仍然提供相同的接口(interface)。

我所有的类都是模板,因为会有一些参数可以是 floatint 或其他任何类型。

但是,我在让所有模板很好地协同工作时遇到了一些麻烦。我遇到的错误与未知模板名称有关

我有一个 MWE 应该可以帮助您了解我在说什么,如果我的解释有点不对(对此表示赞赏!)

├── child.h
├── child_impl.h
└── main.cpp
main.cpp
#include "child.h"
#include <iostream>

int main()
{
    mwe::Child<float> *child_0;
    mwe::Child<float> *child_1;
    mwe::ChildFactory<float> = child_factory;

    int input_param_1 = 5;
    child_0 = child_factory.get_child(1, input_param_1);
    child_1 = child_factory.get_child(2, input_param_1);
    std::cout << child_0->method1() << "\n";
    std::cout << child_1->method1() << "\n";
    return 0;
}

child .h

#ifndef CHILD_H
#define CHILD_H

#include "child_impl.h"
#include <stdexcept>
#include <iostream>

namespace mwe
{
template<typename T>
    class Base
    {
    public:
        Base(){};
        virtual int method1() = 0;
        virtual T method2() const = 0;

    };

template<typename T>
    class Child : public Base<T>
    {
        public:
            Child(int input_param_1)
                : Base<T>(),
                input_param_1(input_param_1){};

            virtual int method1() = 0;
            virtual T method2() const = 0;

            protected:
           int input_param_1;
     };

template<typename T>
    class ChildFactory
    {
    private:
      Child<T> * _child;
    public:
      Child<T> * get_child(int choice,
                       int input_param_1)
      {
      switch(choice)
        {
        case 1:
          _child = new Child_Imp_0<T>(input_param_1);
        case 2:
          _child = new Child_Imp_1<T>(input_param_1);

        default:
          throw std::invalid_argument("recieved in valid layer type");
        }
      return _child;
    }
};

};
#endif //CHILD_H

child_impl.h

#ifndef CHILD_IMPL_H
#define CHILD_IMPL_H

#include "child.h"

namespace mwe
{
    template<typename T>
    class Child_Imp_0 : public Child<T>
    {
    public:
    Child_Imp_0(int input_param_1)
: Child<T>(input_param_1),
    input_param_2(10 * input_param_1)
      {};

  int method1()
  {
    return 0;
  };

  T method2() const
  {
    return 0;
  };

protected:
  int input_param_2;
};

  template<typename T>
class Child_Imp_1 : public Child<T>
{
public:
Child_Imp_1(int input_param_1)
  : Child<T>(input_param_1),
    input_param_2(100 * input_param_1)
      {};

  int method1()
  {
    return 1;
  };

  T method2() const
  {
    return 0;
  };

protected:
  int input_param_2;
};
}
#endif //CHILD_IMPL_H

有没有想过如何让它发挥作用?

我一直在寻找相关问题,但到目前为止无济于事。 This questionthis是相关的,以及其他一些。然而,他们似乎正在处理我难以应用于我的问题的其他复杂问题。

或者,是否有任何替代设计可以提供相同的功能?

最佳答案

这是编译器生成的错误毫无帮助的罕见情况之一。

那是因为你的代码问题发生在预处理期间,甚至在编译器有机会开始解释代码之前。

具体来说,让我们看看当我们将 #include child_impl.h 替换为文件内容时 child.h 是什么样子(因为这就是全部 # include 毕竟是这样的):

#ifndef CHILD_H
#define CHILD_H

#ifndef CHILD_IMPL_H
#define CHILD_IMPL_H

#include "child.h"

namespace mwe
{
   template<typename T>
   class Child_Imp_0 : public Child<T> 
   { ... };
}
#endif 

#include <stdexcept>
#include <iostream>

namespace mwe
{
  ...
}
#endif

现在,如果我们展开 #include child.h:

#ifndef CHILD_H
#define CHILD_H

#ifndef CHILD_IMPL_H
#define CHILD_IMPL_H

#ifndef CHILD_H
// COMPLETELY SKIPPED, since CHILD_H has been defined on the second line!
#endif

namespace mwe
{
   template<typename T>
   class Child_Imp_0 : public Child<T>  // BAM, Child has not been defined yet.
   { ... };
}
#endif 

#include <stdexcept>
#include <iostream>

namespace mwe
{
  ...
}
#endif

为了解决这个问题,您需要以某种方式打破循环依赖。正如@MooingDuck 在评论中所说,将 Factory 移动到它自己的专用 header 会很容易做到这一点。

关于c++ - 模板子类的工厂,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53487253/

相关文章:

c++ - 为什么我的程序在 64 GB RAM 系统上占用的内存不超过 2 GB?

c++ - 如何在值为 std::set 的 std::map 中使用 emplace() (从某物映射到集合)?

c++ - 如何找出二进制文件中使用的是哪个 C++ 标准?

c++ - 如何在模板类方法中将方法指针作为参数传递

c++ - 如何断言模板参数的类型 STL 迭代器类型

c++ - 您如何注册相互依赖的 Qt QML Singleton?

c++ - 具有动态分配内存的 C++ 对象的参数传递

c++ - 为什么我可以在 C++ 中将非 void 成员函数称为 void 成员函数?

c++ - type、value_type 和 element_type 之间有什么区别,何时使用它们?

c++ - 将模板化基类的子类添加到没有超基类的容器中?