重写派生类中的枚举值
Overriding enum values in derived class
我有一个class A
,它使用了一些枚举,如下所示:
enum DataType
{
First,
Second,
Third
}
并且连续地为他们分配了一些在代码中使用的值。
现在,我必须写另一个与class A
非常相似的class B
,我计划为此做一个class Parent
并从中得出class A
和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 ...
}
我想到的一种天真的方法是在两个类中定义一个虚函数,有一个switch case
,所以我必须调用虚函数并使用它返回的内容,而不是使用枚举。
但是,有没有更好的方法呢?通过使用一些我不知道的继承属性?
一个简单的解决方案是在每个成员中定义一个enum DataType
。这不会引入运行时或存储开销。但在这种情况下,行为是静态的;用户只能根据静态类型访问枚举。如果枚举值遵循与示例中类似的模式,则可以使用模板生成枚举甚至整个类。
您建议采用动态方法:使用虚拟函数。这会产生一些开销,但提供了运行时多态性。在这种情况下,用户可以访问特定于动态类型的枚举,而无需知道该类型是什么。
这两种方法甚至可以结合使用,以便同时拥有这两种方法。
我只是将派生类的类型发送到父类函数:
// 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);
}
};
此模式避免模板化整个基类,并且您仍然可以使用虚拟多态性。您只模板化受保护部分中需要枚举的部分。
现场示例
A
和 B 的数据类型是不同的类型,因此 Parent 类必须是模板:
template<typename DataType>
class Parent
{
public:
// example method
virtual bool isFirst(DataType value) const
{
// do something with value, e. g.
return (value == DataType::First);
}
};
enum class DataTypeA
{
First = 1,
Second = 2
};
class A : public Parent<DataTypeA>
{
};
enum class DataTypeB
{
First = 18,
Second = 19
};
class B : public Parent<DataTypeB>
{
};
int main()
{
A a;
B b;
std::cout << "a.isFirst(DataTypeA::First): " << (a.isFirst(DataTypeA::First) ? "true" : "false") << std::endl;
std::cout << "a.isFirst(DataTypeA::Second): " << (a.isFirst(DataTypeA::Second) ? "true" : "false") << std::endl;
std::cout << "b.isFirst(DataTypeB::First): " << (b.isFirst(DataTypeB::First) ? "true" : "false") << std::endl;
std::cout << "b.isFirst(DataTypeB::Second): " << (b.isFirst(DataTypeB::Second) ? "true" : "false") << std::endl;
return 0;
}
请注意,我使用了枚举类而不是(旧式(枚举,以防止遇到枚举值的歧义。
一种方式:
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.
}
相关文章:
- 不带大括号的枚举形式
- 枚举环境变量的惯用C++14/C++17方法
- 类似枚举的计算常量
- 如何正确实现和访问运算符的各种自定义枚举器
- 错误:从"int"到枚举c++的转换无效
- C++中构造函数中的枚举
- 访问在 C++ 结构中声明的枚举变量
- 枚举类'classname'的多重定义
- 强枚举类型定义:Clang Bug 还是 C++11 标准不确定性?
- typedef 枚举和枚举类有什么区别?
- 为什么我的开关/机箱在使用枚举时默认?
- 类似枚举的派生类
- 如何在不实例化派生类的情况下管理一组派生类枚举
- 重写派生类中的枚举值
- 奇怪的是在派生类中使用枚举的经常性模式
- 虚拟方法返回代表派生对象类型的枚举 - 是否可以(在设计方面)
- 使用具有相同名称的(无作用域)基类枚举初始化派生类枚举
- 枚举可执行文件C++派生类
- 模板和派生类定义:错误:"myClass"不是类、命名空间或枚举
- 如何使用包含不同typedef枚举的派生类模板设置构造函数初始化列表