c++ - C++ 中具有用户可扩展类型参数的类型化类

标签 c++ enums shared-libraries

假设您正在编写一个库,为一个类提供某种“类型”参数。对于这个可能使用枚举:

namespace MyLib {
  class Event {
  public:
    enum EventType { TYPE1, TYPE2, ... };
    Event(EventType _type) : type(_type) { }
  private:
    EventType type;
  }
}

然后实例化:

new MyLib::Event(Event::TYPE1);

到目前为止还不错。但是,如果您希望用户能够扩展事件类型列表怎么办?如果类型属性是枚举,这是不可能的。

低质量的可能性包括要求他们#define 自定义事件名称,或者简单地使用字符串,尽管这些似乎都不是最佳选择。

有通用的解决方案吗?

一个建议是使用 struct EventType 返回枚举中指定范围内的值。然而,虽然这解决了编译器安全问题,但它没有解决添加命名类型的问题——它需要用户将这些添加到全局范围。

解决后者而不是前一个问题的一种可能性是将 EventType typedef 为一个完整类型,并留给用户将自定义类型添加到库的命名空间或他们自己的命名空间。提供唯一值的工厂方法可以作为事件的一部分提供:

#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 中的构造函数定义和自动建议中提供了一个有用的语法提示,并且它可以防止用户类型不得不污染全局范围,这可能是更大的问题。

有没有更好的方法来指定一个有限的、经过编译器检查但用户可扩展的值集作为类或函数/方法的类型参数?

最佳答案

我认为最好的办法是简单地将事件类型作为普通整数类型,使用枚举来定义内置类型,并提供用户定义的最小值和最大值,用户可以在这些值之间创建自己的整数值有一个单独的枚举器。然后,您只需使用断言来确保基本事件不会尝试处理未知事件类型。

编辑:请注意,具有某些可以理解的类型和一些不可以理解的类型的基事件类可能是脆弱的,除非它只是保存数据供子类稍后再次挑选。即使在那种情况下,考虑替代设计可能会更好。您能否详细说明事件类型设置后如何使用

EDIT2:我想我现在理解得更好了,事件存储事件类型,事件消费者可以从事件中检索它。如果消费者了解扩展事件类型,它可以进行适当的处​​理,否则委托(delegate)、断言或简单地不进行任何操作。鉴于此,我认为使用完整的事件类型似乎不错。

关于c++ - C++ 中具有用户可扩展类型参数的类型化类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11905757/

相关文章:

c++ - 运营商重载奇怪的输出

java - 使用maven打包时如何调用SO原生库?

linker - 如何查看共享库加载顺序

c++ - 什么是 undefined reference /未解析的外部符号错误,我该如何解决?

c++ - 通过矩阵中 N 个检查点的两点之间的最短路径

c++ - 将数据存储到多维数组中

ios - 如何在 Swift 协议(protocol)可选函数中使用枚举作为参数

c# - 在 C# 中将枚举列表转换为标志

java - 枚举数组到字符串数组

linux - 检索共享对象的文件路径(linux)