假设您正在编写一个库,为一个类提供某种“类型”参数。为此,可能会使用枚举:
namespace MyLib {
class Event {
public:
enum EventType { TYPE1, TYPE2, ... };
Event(EventType _type) : type(_type) { }
private:
EventType type;
}
}
然后实例化:
new MyLib::Event(Event::TYPE1);
到目前为止还好。但是,如果您希望用户能够扩展事件类型列表怎么办?如果 type 属性是枚举,这是不可能的。
低质量的可能性包括要求他们#define
自定义事件名称,或者简单地使用字符串,尽管这些似乎都不是最理想的。
有一个通用的解决方案吗?
一个建议是使用 astruct EventType
返回枚举中指定范围内的值。然而,虽然这解决了编译器安全问题,但它并没有解决添加命名类型的问题——它需要用户将这些添加到全局范围。
解决后一个问题但不是前一个问题的一种可能性是将 EventType 类型定义为一个整体类型,并将其留给用户将自定义类型添加到库的名称空间或他们自己的名称空间。提供唯一值的工厂方法可以作为 Event 的一部分提供:
#include <iostream>
#include <vector>
namespace MyLib {
namespace EventType {
typedef int T;
enum { TYPE1, TYPE2, Count};
}
class Event {
public:
Event(EventType::T _type) : type(_type) { }
EventType::T type;
static EventType::T registerType() { return _typeid++; }
private:
static int _typeid;
};
}
MyLib::EventType::T MyLib::Event::_typeid = EventType::Count;
// The user can then add types, including to the library's namespace
// (which may or may not be a good idea)
namespace MyLib { namespace EventType {
MyLib::EventType::T MYTYPE = MyLib::Event::registerType();
} }
int main() {
MyLib::Event ev1(MyLib::EventType::TYPE2);
MyLib::Event ev2(MyLib::EventType::MYTYPE);
std::cout << ev1.type << std::endl;
std::cout << ev2.type << std::endl;
return 0;
}
输出:
1
2
虽然这在技术上并未将参数限制为一组已注册的类型,但 typedef 和命名空间在 IDE 中的构造函数定义和自动建议中提供了有用的语法提示,并且它可以防止用户类型不得不污染全局范围,从而也许是更大的担忧。
有没有更好的方法来指定有限的、经过编译器检查但用户可扩展的值集作为类的类型参数,或者通常是函数/方法?