模板化子工厂 Class
Factory for Templated Child Class
我正在尝试使用 class 继承和工厂方法。
基本结构是我有一个基classBase
,和一个派生classChild
。
方法 ChildFactory
允许选择 Child
的不同实现,它们仍然提供相同的接口。
我的所有 classes 都是模板,因为会有一些参数可以是 float
s 或 int
s 或其他。
但是,我在让所有模板很好地协同工作时遇到了一些问题。我遇到的错误与未知模板名称有关
我有一个 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 question and 是相关的,还有其他一些。然而,他们似乎正在处理我难以应用于我的问题的其他复杂问题。
或者,是否有任何替代设计可以提供相同的功能?
这是编译器生成的错误极其无用的罕见情况之一。
那是因为你的代码问题发生在预处理期间,甚至在编译器有机会开始解释代码之前。
具体来说,让我们看看当我们将 #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 会很容易做到这一点。
我正在尝试使用 class 继承和工厂方法。
基本结构是我有一个基classBase
,和一个派生classChild
。
方法 ChildFactory
允许选择 Child
的不同实现,它们仍然提供相同的接口。
我的所有 classes 都是模板,因为会有一些参数可以是 float
s 或 int
s 或其他。
但是,我在让所有模板很好地协同工作时遇到了一些问题。我遇到的错误与未知模板名称有关
我有一个 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 question and
或者,是否有任何替代设计可以提供相同的功能?
这是编译器生成的错误极其无用的罕见情况之一。
那是因为你的代码问题发生在预处理期间,甚至在编译器有机会开始解释代码之前。
具体来说,让我们看看当我们将 #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 会很容易做到这一点。