我有一些Base
类,其中包含虚拟方法foo()
。我需要生成几个结构完全相同的子类,并以不同的方式覆盖foo()
。我想出了这个简单的非类型参数模板:
template<const int Index>
class Derived : public Base
{
virtual void foo() {....};
};
typedef Derived<1> Derived_1;
typedef Derived<2> Derived_2;
...
...
然后方法foo
专门用于每种情况。
我对这个策略并不完全满意,因为你需要小心索引冲突(尽管这没什么大不了的),并且实现文件失去了可读性,因为你需要知道索引'2'或'3'对应于什么。最好使用字符串
typedef Derived<"Derived_2"> Derived_2;
但不允许使用字符串文字作为模板参数。
这是在这种情况下使用的推荐模式吗?还有什么更好的? (也许这是一个已知的模式,甚至有一个名字,但我不知道该寻找什么。)
答案 0 :(得分:2)
似乎用继承建模这种关系更接近你想要实现的语义。
struct Derived1 : Derived
{
using Derived::Derived;
virtual void foo() {
std::cout << "Derived1" << std::endl;
};
};
struct Derived2 : Derived
{
using Derived::Derived;
virtual void foo() {
std::cout << "Derived2" << std::endl;
};
};
使用此版本,您可以愉快地将任何DerivedN
版本用作Derived
个对象,因此在它们之间进行转换或在不同版本上一起操作比将所有交叉派生成员函数更容易模板。
继承using Derived::Derived;
可能具有的任何非默认构造函数需要Derived
声明。
答案 1 :(得分:1)
您可以使用预处理器定义更清晰地执行此操作:
#define DERIVED1 1
#define DERIVED2 2
typedef Derived<DERIVED1> Derived_1;
typedef Derived<DERIVED2> Derived_2;
或者也许是枚举? (我不确定,你应该测试一下)。
但是不要犹豫,在你的代码中记录它,这可能是最好的方式。
答案 2 :(得分:1)
如何使用define而不是数字?至少它更清楚。
#define DERIVED_2 2
typedef Derived<DERIVED_2> Derived_2;
但是并不清楚派生类之间的区别是什么。当然,他们不仅仅是数字。
答案 3 :(得分:1)
我建议使用枚举作为模板参数:
enum class type {foo, bar};
template<type name>
class Derived //...
{};
typedef Derived<type::foo> Derived_foo;