gpt4 book ai didi

c++ - 避免在消息传递中向下转型的设计模式

转载 作者:太空狗 更新时间:2023-10-29 23:37:11 26 4
gpt4 key购买 nike

基类 MessageHandler 具有派生类。他们想互相传递信息。消息可以属于不同的类,但可以共享一个基类。每个 MessageHandler 如何避免向下转换收到的消息?是否可以通过某种方式对 MessageHandler 上的虚拟 receiveMessage 函数进行模板参数化?

本质上,我试图用不会向下转换的代码替换以下代码,并且希望是编译时的代码:

// ...
virtual void MessageHandler::receiveMessage(Message &msg) = 0;
// ...

// to receive a message
void DerivedMessageHandler::receiveMessage(Message& msg)
{
switch (msg.MsgType()) // enum
{
case Message::MessageType::A:
MessageA& = dynamic_cast<MessageA&>(msg);
break;

case Message::MessageType::B:
MessageB& = dynamic_cast<MessageB&>(msg);
break;
default:
// don't process unknown messages
break;
}
}

// to send a message
list<MessageHandler> mhList;
// populate list
for (MessageHandler& mh : mhList)
{
mh.receiveMessage(msg);
}

我知道我不能这样做,但是像这样

template <typename M>
void MessageHandler::receiveMessage(M& msg) {}

并且让每个 DerivedMessageHandler 都专注于 M?什么样的设计模式可以干净地让每个处理程序处理其支持的消息对象?

最佳答案

这很容易做到。通常有两种选择:

提升.变体

不是传递派生类,而是简单地枚举消息可能的类型。这些类型不需要彼此派生。将这些类型包装在 boost::variant 中:

typedef boost::variant<MessageData1, MessageData2, MessageData3, ...> MessageData;

请注意,这意味着可能的消息数据类型必须是可枚举的。 Boost.Variant 的访问方法使得使用这些类型的对象变得容易,而无需确切知道它存储的是哪种类型。

Boost.Any

使用 boost::any 简单地传递任何东西:

void MessageHandler::receiveMessage(const boost::any &msg)
{
const MessageType1 *pMsg = boost::any_cast<MessageType1>(&msg);
if(!pMsg)
//Cannot process
return;

//Process message.
}

boost::any 就像一个类型安全的 void*。它会记住放入其中的确切类型,任何将其转换为不同于存储在其中的内容的其他的尝试都会失败。 boost::any 可以存储任何东西,因此得名。

它也有值语义,所以它可以像它的内容一样被复制。

关于c++ - 避免在消息传递中向下转型的设计模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9321497/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com