【发布时间】:2021-12-10 10:37:49
【问题描述】:
考虑这种布局:
#include <memory>
#include <vector>
struct data{};
struct task {
data* data_ptr = nullptr;
virtual void work() = 0;
};
struct special_task : task {
void work() override { /*work with the data*/ }
};
task 可以访问数据。派生类必须实现它们各自的work() 例程。
现在task_collection 存储数据和任务指针向量,派生类的实例可以添加到该向量:
struct task_collection {
data data;
std::vector<std::unique_ptr<task>> tasks;
template<typename T>
void add() {
this->tasks.push_back(std::make_unique<T>());
this->tasks.back()->data_ptr = &this->data;
}
};
int main() {
task_collection t;
t.add<special_task>();
}
现在这很好用。但是,我想知道是否可以将 data* data_ptr 替换为参考,因为它在这里似乎更合适,并且它也将许多 -> 替换为 .s
但是,如果不更改 special_task 的布局,似乎不可能实现这一点,因为引用需要基类 task 中的构造函数,而派生类会取消其基构造函数:
struct task {
task(data& data) : data_ref(data){}
data& data_ref;
virtual void work() = 0;
};
struct special_task : task {
void work() override { /*work with the data*/ }
};
struct task_collection {
data data;
std::vector<std::unique_ptr<task>> tasks;
template<typename T>
void add() {
this->tasks.push_back(std::make_unique<T>(this->data)); //Error!
}
};
它给出了这个错误:
Error C2664 'special_task::special_task(const special_task &)': cannot convert argument 1 from 'data' to 'const special_task &'
我知道这可以通过添加来“解决”
using task::task;
到每个派生类,因为现在它找到了适当的构造函数。但这并不是真正的解决方案,因为可能有数百个派生类,由多人编写。如果using task::task; 的一个实例丢失,可能会导致头痛。额外的代码行也抵消了使用引用而不是指针带来的好处。
那么有没有办法将task::data_ref 实现为仅修改task_collection 或task 而没有任何派生类的引用?
【问题讨论】:
-
如果没有 using 声明,我认为你不能做你目前正在做的事情。但是,您可以稍微改变您的任务概念。怎么样:工作(数据和数据)而不是工作()?那么你根本不需要数据作为实例变量,只需在调用任务时传递数据即可。
-
您的主要问题是用
.替换->吗?您是否接受将->替换为.get().或者您无法接受? -
@Wutz 如果每个任务都可以拥有自己对数据的引用,那么会有很大的好处,因为除了
work()之外还有更多功能。它们也被传递给其他函数,它们应该在没有额外的data参数的情况下独立工作。 -
@StackDanny 你看到我的问题了吗?
-
如果使用task::task的一个实例;缺少它可能会导致头疼。 指出哪个类缺少
using data::data;的清晰而简单的编译时错误真的令人头疼吗?
标签: c++ inheritance constructor unique-ptr