C++数据类型封装实现过滤视图复用的设计模式及编译问题咨询
问题2 编译错误原因
你遇到的编译错误是两个代码疏漏共同导致的:
- 方法名不匹配:
wrapper_interface的data()方法中调用的是derived()->data_(),但你在wrapper、filtered_wrapper中实现的对外方法名是data(),缺少末尾的下划线,导致名称查找失败,连锁引发do_stuff的参数类型推导异常,最终抛出匹配失败错误。 - CRTP模板参数填写错误:
filtered_wrapper继承wrapper_interface时,第一个模板参数(CRTP要求的派生类自身类型)错误填成了wrapper,而非filtered_wrapper。当你继承filtered_wrapper生成special_filtered_wrapper时,CRTP的静态向下转型会错误转为wrapper*类型,进一步加剧了类型匹配问题。
问题1 替代实现方案
如果你想继续沿用现有CRTP方案,可以先给wrapper_interface加完美转发构造函数,解决多层继承下的非默认构造问题:
template < class Derived, class Base, class DataType > class wrapper_interface : Base { public: // 新增完美转发构造函数,将参数转发给Base类构造 template<typename... Args> wrapper_interface(Args&&... args) : Base(std::forward<Args>(args)...) {} virtual ~wrapper_interface() = default; // 其余原有逻辑不变 };
修改后你用第二种CRTP继承方案定义special_filtered_wrapper时,就可以在自身构造函数中传参给filtered_wrapper的构造函数,完成filtered_data_type的初始化。
如果不想用CRTP,提供两个完全不需要暴露模板给用户、也不用重写10个公共方法的方案:
方案1:非虚接口(NVI) + 类型擦除
把所有公共方法放到非模板的公共基类wrapper_base中,基类声明纯虚的内部数据获取接口,各个子类实现该接口返回自身持有的数据实例。公共方法内部调用该虚接口拿到数据后,在实现侧完成类型转换和do_stuff调用。头文件中只暴露基类的公共方法声明,所有实现逻辑都可以放到cpp文件中,完全不会暴露内部的data_type和模板逻辑。
方案2:宏复用代码
把10个公共方法的实现封装为一个宏定义,在wrapper、filtered_wrapper等各个类的定义内部展开宏即可,不需要写重复代码,也不会引入任何模板。对于只有10个固定方法的场景,这个方案最轻便,维护成本极低,用户侧完全看不到内部实现细节。
内容的提问来源于stack exchange,提问作者user3814483
相关产品推荐
相关产品推荐

