我有一个class A
,其中使用了一些枚举,例如:
enum DataType
{
First,
Second,
Third
}
随后,他们被分配了一些在代码中使用的值。
现在,我必须编写与class B
非常相似的另一个class A
,为此我计划制作一个class Parent
并派生class A
和{ {1}}。但是,我想在两个类中重用class B
。
问题在于,enum DataType
和enum
的这些class A
值应该不同。
对于class B
class A
对于enum DataType
{
First = 1,
Second = 2 ...
}
class B
想到的一种幼稚方法是在两个类中都定义一个虚函数,它们都具有enum DataType
{
First = 18,
Second = 19 ...
}
,因此,除了使用枚举,我还必须调用虚函数并使用其返回的内容。 / p>
但是,还有更好的方法吗?通过使用一些我不知道的继承属性?
答案 0 :(得分:1)
A和B的数据类型是不同的类型,因此Parent类必须是模板:
http://geo.ma/).txt
请注意,我使用了enum类而不是(旧式的)enum,以避免陷入enum值的歧义。
答案 1 :(得分:1)
一种方法:
template<int EnumBegin>
struct Parent {
enum DataType {
First = EnumBegin,
Second, // == First + 1
Third // == Second + 1
};
};
struct A : Parent<0> {};
struct B : Parent<10> {};
int main() {
std::cout << A::Second << '\n'; // Outputs 1.
std::cout << B::Second << '\n'; // Outputs 11.
}
答案 2 :(得分:1)
一个简单的解决方案是在每个成员中定义一个enum DataType
。这不会带来运行时或存储开销。但是在这种情况下,行为是静态的。用户只能基于静态类型访问枚举。如果枚举值遵循与示例相同的模式,则可以生成枚举,甚至可以使用模板生成整个类。
您建议使用动态方法:使用虚函数。这有一些开销,但是提供了运行时多态性。在这种情况下,用户可以访问特定于动态类型的枚举,而无需知道该类型是什么。
这两种方法甚至可以结合在一起使用,从而使两者兼具。
答案 3 :(得分:0)
我只是将派生类的类型发送给父类函数:
// parent not templated!
struct Parent {
// with this pattern, stuff1 could be virtual:
// virtual void stuff1() = 0;
protected:
// static because we can access private
// member through the self object
template<typename T>
static void stuff1_impl(T const& self) {
auto value = /* get the switched on value */;
switch(value) {
case T::DataType::First:
// things for the case1
break;
case T::DataType::Second:
// things for the case1
break;
}
}
};
然后在派生类中:
struct A : Parent {
enum struct DataType {
First = 1, Second
};
// v---- if virtual, add override
void stuff1() /* override */ {
stuff1_impl(*this);
}
};
struct B : Parent {
enum struct DataType {
First = 10, Second
};
// v---- if virtual, add override
void stuff1() /* override */ {
stuff1_impl(*this);
}
};
此模式避免模板化整个基类,并且您仍然可以使用虚拟多态性。您只需在受保护的部分中对需要枚举的部分进行模板化。