仅修改基类或集合类 能否不改动派生类将基类指针换为引用?
解决方案
方案1:基类新增引用访问接口(零侵入,最推荐)
该方案仅需修改task基类,完全不需要调整任何派生类代码,即可满足使用.访问数据的需求:
struct task { data* data_ptr = nullptr; // 新增两个重载的引用获取接口 data& data_ref() { // 可按需添加assert(data_ptr != nullptr)做调试期检查 return *data_ptr; } const data& data_ref() const { return *data_ptr; } virtual void work() = 0; };
原有派生类中写data_ptr->xxx的代码直接替换为data_ref().xxx即可使用.访问成员,和直接持有引用的使用体验完全一致。原有task_collection的add逻辑不需要做任何修改,同时还能兼容老代码中直接使用data_ptr的写法,升级风险为零。
方案2:基类直接持有可赋值的引用包装
如果希望在task中直接定义语义等价于引用的成员变量,可以使用C++标准库的std::reference_wrapper解决引用无法默认构造、无法重新绑定的问题,同样不需要修改任何派生类代码:
#include <functional> // 引入std::reference_wrapper所需头文件 struct task { // 用reference_wrapper替代原生引用,支持默认构造和赋值 std::reference_wrapper<data> data_ref = *static_cast<data*>(nullptr); // 可选:添加访问器省略.get()调用,使用体验和原生引用一致 data& get_data() { return data_ref.get(); } virtual void work() = 0; };
task_collection的add逻辑仅需调整赋值语句即可,其余完全不变:
template<typename T> void add() { this->tasks.push_back(std::make_unique<T>()); this->tasks.back()->data_ref = this->data; // 直接为reference_wrapper赋值 }
使用时通过data_ref.get().xxx或者get_data().xxx即可用.访问数据成员,语义和原生引用完全一致。
内容的提问来源于stack exchange,提问作者Stack Danny
相关产品推荐
相关产品推荐

