现代C++如何不使用if/switch,根据命令类型查找对应命令处理程序
实现思路
核心是把类型匹配逻辑交给编译器静态分发/标准库实现,完全避免手动编写if/switch分支。下面给出两种主流的现代C++实现方案:
方案1:C++17及以上使用 std::variant + std::visit(推荐)
不需要继承公共基类,代码更简洁,运行时无额外开销:
#include <iostream> #include <variant> // 重载lambda辅助模板,用于多类型匹配 template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; }; template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>; // 命令定义,不需要继承公共基类 struct CommandA { int a = 32; }; struct CommandB { double b = 56.43; }; // 处理器定义保持不变 class ACommandHandler { public: void Process(CommandA command) { std::cout << command.a; } }; class BCommandHandler { public: void Process(CommandB command) { std::cout << command.b; } }; // 命令类型集合定义 using Command = std::variant<CommandA, CommandB>; class Intermediator { public: void Delegate(Command command) { // 标准库visit自动匹配对应类型的处理逻辑,无任何手动分支 std::visit(overloaded{ [this](CommandA cmd) { handlerA.Process(cmd); }, [this](CommandB cmd) { handlerB.Process(cmd); } }, command); } private: ACommandHandler handlerA; BCommandHandler handlerB; }; int main() { Intermediator intermediator; CommandA a; intermediator.Delegate(a); // 输出32 CommandB b; intermediator.Delegate(b); // 输出56.43 return 0; }
方案2:访问者模式(兼容C++11/14)
如果需要兼容旧标准,可以用经典访问者模式实现动态分发:
#include <iostream> class CommandVisitor; // 基类增加访问者接口 struct Command { virtual void Accept(CommandVisitor& visitor) = 0; virtual ~Command() = default; }; struct CommandA; struct CommandB; class CommandVisitor { public: virtual void Visit(CommandA& cmd) = 0; virtual void Visit(CommandB& cmd) = 0; }; struct CommandA : Command { int a = 32; void Accept(CommandVisitor& visitor) override { visitor.Visit(*this); } }; struct CommandB : Command { double b = 56.43; void Accept(CommandVisitor& visitor) override { visitor.Visit(*this); } }; // 处理器保持不变 class ACommandHandler { public: void Process(CommandA command) { std::cout << command.a; } }; class BCommandHandler { public: void Process(CommandB command) { std::cout << command.b; } }; // 中介类实现访问者接口 class Intermediator : public CommandVisitor { public: void Delegate(Command& command) { command.Accept(*this); } void Visit(CommandA& cmd) override { handlerA.Process(cmd); } void Visit(CommandB& cmd) override { handlerB.Process(cmd); } private: ACommandHandler handlerA; BCommandHandler handlerB; }; int main() { Intermediator intermediator; CommandA a; intermediator.Delegate(a); // 输出32 CommandB b; intermediator.Delegate(b); // 输出56.43 return 0; }
说明:整个流程完全没有手动判断类型的if/switch分支,分发逻辑由虚函数表的动态调用实现
内容的提问来源于stack exchange,提问作者Jarkness Ferture
相关产品推荐
相关产品推荐

