C++运行时动态函数返回类型实现方案咨询(MTProto开发场景)
C++ MTProto TLObject动态类型解析解决方案
方案1:访问者模式(兼容C++11及以上版本,无需修改工厂返回结构)
- 实现逻辑:
- 定义访问者基类,为所有已知子类添加
visit重载方法:
class ParentVisitor { public: virtual void visit(FirstChild& obj) = 0; virtual void visit(SecondChild& obj) = 0; // 所有其他子类依次添加重载 };- 给
Parent基类添加纯虚accept方法:
class Parent { public: virtual void accept(ParentVisitor& visitor) = 0; // 原有基类逻辑保留 };- 每个子类实现
accept方法:
void FirstChild::accept(ParentVisitor& visitor) { visitor.visit(*this); } void SecondChild::accept(ParentVisitor& visitor) { visitor.visit(*this); }- 业务侧自定义访问者子类实现对应类型的处理逻辑,拿到工厂返回的
Parent*指针后调用accept方法即可自动匹配到对应子类的处理分支,无需手动类型转换。
- 定义访问者基类,为所有已知子类添加
方案2:std::variant + std::visit(C++17及以上推荐,性能最优)
因为你提前知晓所有可能的子类范围,完全可以直接用变体类型存储返回结果,避开继承体系的虚函数开销,也是现有MTProto开源实现的主流方案:
- 实现逻辑:
- 定义变体类型包含所有可能的子类:
using TLObject = std::variant<FirstChild, SecondChild, 其他所有子类...>;- 修改
Factory::read方法返回TLObject类型,根据传入的ID构造对应子类存入变体即可。 - 业务侧处理时直接用
std::visit匹配类型:
auto obj = Factory::read(id); std::visit([](auto&& real_obj) { // 这里real_obj就是对应子类的实例,可以直接调用独有成员 if constexpr (std::is_same_v<std::decay_t<decltype(real_obj)>, FirstChild>) { // 处理FirstChild独有逻辑 } else if constexpr (std::is_same_v<std::decay_t<decltype(real_obj)>, SecondChild>) { // 处理SecondChild独有逻辑 } // 其他子类依次添加分支即可 }, obj);
方案3:ID分支派发(轻量场景适用)
如果子类数量可控,可直接通过ID判断类型后安全转换:
- 每个子类定义静态常量
TL_ID对应协议中的构造ID,拿到Parent*指针后先调用基类的get_id()方法获取ID,走switch分支做static_cast即可:
Parent* obj = Factory::read(id); switch(obj->get_id()) { case FirstChild::TL_ID: { auto* real_obj = static_cast<FirstChild*>(obj); // 处理FirstChild逻辑 break; } case SecondChild::TL_ID: { auto* real_obj = static_cast<SecondChild*>(obj); // 处理SecondChild逻辑 break; } // 其他子类依次添加分支 }
该方案实现成本最低,不需要修改原有类结构,只要保证ID和类型的对应关系正确即可。
内容的提问来源于stack exchange,提问作者mattiabrandon
相关产品推荐
相关产品推荐

