【发布时间】:2021-06-11 19:49:13
【问题描述】:
我在尝试调用附加到向量的对象的覆盖函数时遇到问题。我不太确定我是否只是不完全理解指针和引用,所以我不太确定在调试这个问题时要寻找什么。
这是我的代码:
#include <iostream>
#include <vector>
class Task {
public:
Task(std::vector<Task> *list) {
list->push_back(*this);
}
virtual void Run() {
std::cout << "Called Task Run!" << std::endl;
}
};
class OverrideTask : public Task {
public:
OverrideTask(std::vector<Task> *list) : Task(list) {}
void Run() override {
std::cout << "Called Override Run!" << std::endl;
}
};
int main() {
std::cout << "Main method entered" << std::endl;
std::vector<Task> listOfTasks;
OverrideTask ot = OverrideTask(&listOfTasks);
Task t = Task(&listOfTasks);
for(int i = 0; i < listOfTasks.size(); i++) {
listOfTasks[i].Run(); // Will print "Called Task Run!" twice.
}
ot.Run(); // Prints "Called Override Run!"
t.Run(); // Prints "Called Task Run!"
}
当我遍历向量时,似乎无法调用覆盖函数,但是当我直接从对象调用它们时,它们似乎可以工作。有人能指出我正确的方向吗?
【问题讨论】:
-
您已成为slicing 的受害者。 IE。
vector<Task>.push_back(OverrideTask{})将剥离被覆盖的部分并仅保留其Task部分。除此之外代码没问题,只要使用std::vector<std::unique_ptr<Task>>就可以了。 -
你也成为了滥用构造函数以获得副作用的受害者。您永远无法确定是为临时对象、本地对象还是更持久的对象调用构造函数。因此,更好的设计确实将构造函数集中在构造上,并将使用新对象的代码(即负责将所选任务添加到任务列表中)移动到另一个地方。
-
cppcheck 还建议对带有一个参数的构造函数使用显式。