无需复制类代码,能否在C++中修改类的特定类型别名并自动生成变体类?
能否在C++中修改类的特定类型别名并自动生成变体类?
当然可以实现你的需求,但我得先给你提个醒:尽量别用宏,C++本身的模板机制就能优雅解决这个问题,而且比宏安全得多,维护起来也省心。
你的核心痛点是不想重复编写几乎一模一样的类——只是把variable的类型从int换成double,就得复制一整套代码,这太麻烦了。问题出在你现在把Derived写成了非模板类,直接绑定到了BaseT<true>上,没法灵活切换类型。其实只要把Derived也改成模板类,复用BaseT的模板参数,就能自动生成不同类型版本的变体类,完全不用手动复制代码。
推荐方案:把Derived改成模板类
重构后的代码会是这样:
template<bool int_mode> class BaseT { public: using variable = std::conditional_t<int_mode, int, double>; BaseT() = default; virtual variable foo(variable var) { return 0; } }; // 把Derived也改成模板类,继承对应版本的BaseT template<bool int_mode> class DerivedT : public BaseT<int_mode> { public: // 复用基类的variable类型别名 using variable = typename BaseT<int_mode>::variable; variable a, b, c; DerivedT() : a(10), b(20), c(30) {} // foo的逻辑完全复用,编译器会自动适配不同的variable类型 variable foo(variable var) override { return var * a * b * c; } }; // 定义别名对应你原来的类,保持代码兼容性 using Derived = DerivedT<true>; using DerivedDouble = DerivedT<false>;
这样一来,Derived和DerivedDouble会自动由编译器生成,foo的逻辑完全不用重复写,类型也能自动匹配。
关于你的runDerivedDouble函数
你原来想把Derived&直接转换成DerivedDouble,但这两个是完全不同的类,没法直接转换。不过你可以手动复制成员变量(注意类型转换),然后调用对应版本的foo:
double runDerivedDouble(Derived& cls) { DerivedDouble cls_double; // 把int类型的成员转换成double cls_double.a = static_cast<double>(cls.a); cls_double.b = static_cast<double>(cls.b); cls_double.c = static_cast<double>(cls.c); // 调用double版本的foo,比如传入一个double参数 return cls_double.foo(2.5); }
迫不得已的选择:用宏生成类
如果你因为历史代码依赖,实在不能修改现有的Derived类,那宏可以临时解决问题,但我非常不推荐——宏是文本替换,没有类型检查,很容易出现莫名其妙的错误,调试起来也头疼。示例代码如下:
#define DEFINE_DERIVED_CLASS(CLASS_NAME, BASE_CLASS) \ class CLASS_NAME : public BASE_CLASS { \ public: \ using variable = typename BASE_CLASS::variable; \ variable a, b, c; \ CLASS_NAME() : a(10), b(20), c(30) {} \ variable foo(variable var) override { \ return var * a * b * c; \ } \ }; // 生成原来的Derived DEFINE_DERIVED_CLASS(Derived, Base) // 生成DerivedDouble DEFINE_DERIVED_CLASS(DerivedDouble, BaseDouble)
总结
优先选择模板类的方案,这是C++原生的、类型安全的解决方案,代码清晰易维护。宏只是万不得已的权宜之计,能不用就不用。
备注:内容来源于stack exchange,提问作者Sam Moldenha
相关产品推荐
相关产品推荐

