如何优雅地转换switch +枚举与多态 [英] How to Elegantly convert switch+enum with polymorphism

查看:964
本文介绍了如何优雅地转换switch +枚举与多态的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图用类型类替换简单枚举。也就是说,一个类派生自一个基类为每个类型。例如代替:

I'm trying to replace simple enums with type classes.. that is, one class derived from a base for each type. So for example instead of:

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类,使用一个函数指针容器,所有这些都似乎破坏了通过用多态替换开关使代码更容易维护的目的。

I have seen many ways to do this which all seem less elegant even then the basic switch statement. Using dyanimc_cast, inheriting from a messageHandler class that needs to be updated every time a new message is added, using a container of function pointers, all seem to defeat the purpose of making code easier to maintain by replacing switches with polymorphism.

这是尽可能接近:(我使用模板,以避免从一个知道的处理程序接口继承)

This is as close as I can get: (I use templates to avoid inheriting from an all-knowing handler interface)

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";
    }
};

显然,这不会编译,但我希望它得到我的问题。 >

Obviously, this doesn't compile but I'm hoping it gets my problem accross.

推荐答案

好了,在给予dynamic_cast和多重继承之后,我想出了这个感谢 Anthony Williams jogear.net

Well, after giving in to dynamic_cast and multiple inheritance, I came up with this thanks to Anthony Williams and jogear.net

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;
}

这篇关于如何优雅地转换switch +枚举与多态的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆