gpt4 book ai didi

c++ - 访问者模式是否比受控使用 RTTI 更好?

转载 作者:行者123 更新时间:2023-12-02 10:02:31 28 4
gpt4 key购买 nike

我经常发现自己试图使用 boost/QT 信号解耦对象。实现这一点的简单方法是针对我要通信的每个具体类型,创建一个新的信号和插槽签名并连接所有相关对象。这导致了访问者模式,理想情况下我想发出一个访问者并让所有的监听类接收访问者并执行一个 Action 。接口(interface)如下所示:

class IVisitor
{
public:
Visit(IListener* Listener);
Visit(ConcreteListener1* Listener);
Visit(ConcreteListener2* Listener);
//And so on from here
};

同样,如果我想要多个命令,我需要让多个访问者:
class IListener
{
public:
Visit(IVisitor* Listener);
Visit(ConcreteVisitor1* Listener);
Visit(ConcreteVisitor2* Listener);
//And so on from here
};

对我来说,这似乎违反了打开/关闭原则,因为每次我想连接一个新的监听器或实现一个新的访问者时,我总是不得不返回更新我的接口(interface)。理想情况下,这将使用双重分派(dispatch),并且如果没有专门的接口(interface)存在,则能够使基类保持不变,仅根据他们使用基类接口(interface)接受的访问者来更改派生类。我知道这在 C++ 中是不可能的,因为函数重载和参数类型基于编译时信息。

一般来说,这都是关于在不支持它的程序中重新实现多个调度。

我看过很多关于访问者模式的争论,这似乎是人们使用和讨厌的模式。它似乎是它的访问者模式或dynamic_cast?我已经实现了一个模板化的帮助类,它可以在使用 dynamic_cast 以实现更好的维护时自动执行可怕的 if-else 逻辑。所以我的问题是......当逻辑维护在很大程度上自动化时,使用 dynamic_cast 的陷阱是否比访问者模式中提到的陷阱更糟糕?

编辑:

std::visit 确实似乎是解决多分派(dispatch)问题的好方法。我能够使用以下一个衬垫创建一个简单的消息传递系统:
std::visit(overloaded{ [&](auto arg) {Listener->Recieve(arg); } }, pCommand->AsVariant());

最佳答案

以访客模式,

当一个新的监听器被添加到 IVisitor ,您可以保证现有访问者必须处理该新监听器。

用简单的dynamic_cast ,未处理的监听器更有可能。
取决于(每个,(所以没有统一的行为))类如何实现它,您可能会抛出不受支持的监听器,或者回退到“默认实现”(什么都不做)。
dynamic_cast 的替代品是 std::variant对于访问者,需要了解所有监听器类型的用法。
std::variant有一个 std::visit它甚至可以进行多次调度:-)

所以,像:

using ListenerVariant = std::variant<ConcreteListener1*, ConcreteListener2* /*..*/>;

class IListener
{
public:
virtual ListenerVariant AsVariant() = 0;
// ...
};

进而
std::visit(overloaded{[](ConcreteListener1* l){/*..*/},
[](ConcreteListener2* l){/*..*/}},
listener.AsVariant());

您可以保证所有案件都得到处理,(您甚至可以有后备)。

关于c++ - 访问者模式是否比受控使用 RTTI 更好?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61937108/

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