如何通过多态优雅地转换 switch+enum

2024-02-06

我正在尝试用类型类替换简单的枚举......也就是说,从每种类型的基派生一个类。例如,而不是:

enum E_BASE { EB_ALPHA, EB_BRAVO };
E_BASE message = someMessage();
switch (message) 
{
  case EB_ALPHA: applyAlpha();
  case EB_BRAVO: applyBravo();
}

我想做这个:

Base* message = someMessage();
message->apply(this); // use polymorphism to determine what function to call.

我见过很多方法来做到这一点,即使比基本的 switch 语句都显得不太优雅。使用 dyanimc_cast、继承每次添加新消息时都需要更新的 messageHandler 类、使用函数指针容器,所有这些似乎都违背了通过用多态性替换开关来使代码更易于维护的目的。

这是我能得到的最接近的结果:(我使用模板来避免从无所不知的处理程序接口继承)

class Base
{
public:
    template<typename T> virtual void apply(T* sandbox) = 0;
};

class Alpha : public Base
{
public:
    template<typename T> virtual void apply(T* sandbox)
    {
        sandbox->applyAlpha();
    }
};

class Bravo : public Base
{
public:
    template<typename T> virtual void apply(T* sandbox)
    {
        sandbox->applyBravo();
    }
};

class Sandbox
{
public:
    void run()
    {
        Base* alpha = new Alpha;
        Base* bravo = new Bravo;

        alpha->apply(this);
        bravo->apply(this);

        delete alpha;
        delete bravo;
    }
    void applyAlpha() {
        // cout << "Applying alpha\n";
    }

    void applyBravo() {
        // cout << "Applying bravo\n";
    }
};

显然,这不能编译,但我希望它能解决我的问题。


好吧,在屈服于dynamic_cast和多重继承之后,我想出了这个,感谢安东尼·威廉姆斯 http://www.drdobbs.com/cpp/184429055 and 乔齿轮网 http://jogear.net/dynamic-double-dispatch-and-templates#

class HandlerBase
{
public:
    virtual ~HandlerBase() {}
};

template<typename T> class Handler : public virtual HandlerBase
{
public:
    virtual void process(const T&)=0;
};

class MessageBase
{
public:
    virtual void dispatch(HandlerBase* handler) = 0;

    template<typename MessageType>
    void dynamicDispatch(HandlerBase* handler, MessageType* self)
    {
        dynamic_cast<Handler<MessageType>&>(*handler).process(*self);
    }
};

template<typename MessageType> class Message : public MessageBase
{
    virtual void dispatch(HandlerBase* handler)
    {
        dynamicDispatch(handler, static_cast<MessageType*>(this));
    }
};

class AlphaMessage : public Message<AlphaMessage>
{
};

class BravoMessage : public Message<BravoMessage>
{
};

class Sandbox : public Handler<AlphaMessage>, public Handler<BravoMessage>
{
public:
    void run()
    {
        MessageBase* alpha = new AlphaMessage;
        MessageBase* bravo = new BravoMessage;

        alpha->dispatch(this);
        bravo->dispatch(this);

        delete alpha;
        delete bravo;
    }
    virtual void process(const AlphaMessage&) {
        // cout << "Applying alpha\n";
    }

    virtual void process(const BravoMessage&) {
        // cout << "Applying bravo\n";
    }
};


int main()
{
    Sandbox().run();
    return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何通过多态优雅地转换 switch+enum 的相关文章

  • 使用 gcc 在 Linux 上运行线程构建块 (Intel TBB)

    我正在尝试为线程构建块构建一些测试 不幸的是 我无法配置 tbb 库 链接器找不到库 tbb 我尝试在 bin 目录中运行脚本 但这没有帮助 我什至尝试将库文件移动到 usr local lib 但这又失败了 任何的意见都将会有帮助 确定您
  • 如何从 Visual Studio 将视图导航到其控制器?

    问题是解决方案资源管理器上有 29 个项目 而且项目同时具有 ASP NET MVC 和 ASP NET Web 表单结构 在MVC部分中 Controller文件夹中有大约100个子文件夹 每个文件夹至少有3 4个控制器 视图完全位于不同
  • std::vector 与 std::stack

    有什么区别std vector and std stack 显然 向量可以删除集合中的项目 尽管比列表慢得多 而堆栈被构建为仅后进先出的集合 然而 堆栈对于最终物品操作是否更快 它是链表还是动态重新分配的数组 我找不到关于堆栈的太多信息 但
  • 随着时间的推移,添加到 List 变得非常慢

    我正在解析一个大约有 1000 行的 html 表 我从一个字符串中添加 10 个字符串 td 每行到一个list td
  • 如何连接重叠的圆圈?

    我想在视觉上连接两个重叠的圆圈 以便 becomes 我已经有部分圆的方法 但现在我需要知道每个圆的重叠角度有多大 但我不知道该怎么做 有人有主意吗 Phi ArcTan Sqrt 4 R 2 d 2 d HTH Edit 对于两个不同的半
  • 如何在 C++ 中标记字符串?

    Java有一个方便的分割方法 String str The quick brown fox String results str split 在 C 中是否有一种简单的方法可以做到这一点 The 增强分词器 http www boost o
  • 需要帮助优化算法 - 两百万以下所有素数的总和

    我正在尝试做一个欧拉计划 http projecteuler net问题 我正在寻找 2 000 000 以下所有素数的总和 这就是我所拥有的 int main int argc char argv unsigned long int su
  • 访问外部窗口句柄

    我当前正在处理的程序有问题 这是由于 vista Windows 7 中增强的安全性引起的 特别是 UIPI 它阻止完整性级别较低的窗口与较高完整性级别的窗口 对话 就我而言 我想告诉具有高完整性级别的窗口进入我们的应用程序 它在 XP 或
  • 重载 (c)begin/(c)end

    我试图超载 c begin c end类的函数 以便能够调用 C 11 基于范围的 for 循环 它在大多数情况下都有效 但我无法理解和解决其中一个问题 for auto const point fProjectData gt getPoi
  • 如何定义一个可结构化绑定的对象的概念?

    我想定义一个concept可以检测类型是否T can be 结构化绑定 or not template
  • C 编程:带有数组的函数

    我正在尝试编写一个函数 该函数查找行为 4 列为 4 的二维数组中的最大值 其中二维数组填充有用户输入 我知道我的主要错误是函数中的数组 但我不确定它是什么 如果有人能够找到我出错的地方而不是编写新代码 我将不胜感激 除非我刚去南方 我的尝
  • C# 动态/expando 对象的深度/嵌套/递归合并

    我需要在 C 中 合并 2 个动态对象 我在 stackexchange 上找到的所有内容仅涵盖非递归合并 但我正在寻找能够进行递归或深度合并的东西 非常类似于jQuery 的 extend obj1 obj2 http api jquer
  • 复制目录下所有文件

    如何将一个目录中的所有内容复制到另一个目录而不循环遍历每个文件 你不能 两者都不Directory http msdn microsoft com en us library system io directory aspx nor Dir
  • 相当于Linux中的导入库

    在 Windows C 中 当您想要链接 DLL 时 您必须提供导入库 但是在 GNU 构建系统中 当您想要链接 so 文件 相当于 dll 时 您就不需要链接 为什么是这样 是否有等效的 Windows 导入库 注意 我不会谈论在 Win
  • C# 中的 IPC 机制 - 用法和最佳实践

    不久前我在 Win32 代码中使用了 IPC 临界区 事件和信号量 NET环境下场景如何 是否有任何教程解释所有可用选项以及何时使用以及为什么 微软最近在IPC方面的东西是Windows 通信基础 http en wikipedia org
  • 使用特定参数从 SQL 数据库填充组合框

    我在使用参数从 sql server 获取特定值时遇到问题 任何人都可以解释一下为什么它在 winfom 上工作但在 wpf 上不起作用以及我如何修复它 我的代码 private void UpdateItems COMBOBOX1 Ite
  • 对于某些 PDF 文件,LoadIFilter() 返回 -2147467259

    我正在尝试使用 Adob e IFilter 搜索 PDF 文件 我的代码是用 C 编写的 我使用 p invoke 来获取 IFilter 的实例 DllImport query dll SetLastError true CharSet
  • C# 中最小化字符串长度

    我想减少字符串的长度 喜欢 这串 string foo Lorem ipsum dolor sit amet consectetur adipiscing elit Aenean in vehicula nulla Phasellus li
  • 从 mvc 控制器使用 Web api 控制器操作

    我有两个控制器 一个mvc控制器和一个api控制器 它们都在同一个项目中 HomeController Controller DataController ApiController 如果我想从 HomeController 中使用 Dat
  • 如何确定 CultureInfo 实例是否支持拉丁字符

    是否可以确定是否CultureInfo http msdn microsoft com en us library system globalization cultureinfo aspx我正在使用的实例是否基于拉丁字符集 我相信你可以使

随机推荐