【问题标题】:Is there any way to enforce in C++ (at compile-time) that a derived class defines a nested type?有没有办法在 C++ 中(在编译时)强制派生类定义嵌套类型?
【发布时间】:2014-07-02 17:46:27
【问题描述】:

例如,我有一个基类Event,我想确保从Event 派生的每个类都定义了一个enum class Type 成员,因此T::Type 是任何类T 的有效类型源自Event

【问题讨论】:

  • 没有相当简单的方法。您在这里要解决的真正问题是什么?
  • 您希望这个嵌套类型成为enum class 的事实表明您希望不同的派生类包含不同的——但肯定没有办法保证这一点静态的。例如。在class A : public Event { enum class Type { X }; }; class B : public Event { enum class Type { X }; };A::Type::XB::Type::X之后的类型不同但值相同(转换为int后)。
  • 你是对的。我想这对我来说又回到了绘图板上。我的最终目标是确保对于每种事件,仅使用某种类型(源自Event)。 (即鼠标按钮按下事件使用MouseEvent,而不是KeyboardEvent
  • 模板可以用吗?
  • 您必须决定是关闭您的活动集还是打开以进行扩展。如果关闭,这很容易——只需将enum class Type { Keyboard, Mouse }; 放在基类Event 内即可。如果打开,我会看到 2 个选择:要么要求每个事件类型为自己提供一个您可以确定是唯一的 ID,无论以后添加多少其他事件类型(例如字符串或 GUID),或者每个事件类型向某个全局注册表“注册”自身并从中接收其 ID(这可以通过例如给每个派生类一个 static 其 ctor 注册它的成员来完成)。

标签: c++ inheritance compile-time static-assert


【解决方案1】:

即使阅读了您的评论,我仍然不明白您在这里的真正目标。但是要回答您提出的具体问题:

你所要做的就是使用派生类中的类型,如果它不存在,你会得到一个编译错误。这是最简单的方法。

另一个稍微不同的直接方法是使用在事件类上模板化的策略类:

template <typename T>
struct EventType;

template <>
struct EventType<A>
{
    typedef int Type;
};

【讨论】:

    【解决方案2】:

    因为只有模板才能以任何方式识别这样的事情,所以没有办法强制执行这样的限制。

    不过,您的模板仍然可以使用 来强制执行它们的约束,例如具有名为 alpha 的类型成员并且派生自 beta。

    不过,在你走这条路之前,请确保付出的努力是值得的。

    【讨论】:

      【解决方案3】:

      我不知道使用enum 的便捷方法,但实现目标的更简单方法可能是使用纯虚拟基类。

      class Event 
      {
          virtual int getType() = 0;  // pure virtual function
      };
      
      class Circus : public Event
      {
          // Circus does not implement getType
      };
      
      int main()
      {
          Circus c;   // compile-time error
      }
      

      【讨论】:

      • 强制子类在哪里定义成员类型?
      • @Deduplicator:编译器无法实例化抽象类,因此任何未能实现getType()成员函数的派生类都会导致编译时错误。函数实际做什么仍然是程序员的责任,但这有助于确保它不会被忽视。
      猜你喜欢
      • 2015-04-11
      • 1970-01-01
      • 1970-01-01
      • 2020-06-10
      • 2021-01-12
      • 2012-05-21
      • 2022-01-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多