【问题标题】:Calling the override function in a vector (C++) [duplicate]在向量中调用覆盖函数(C++)[重复]
【发布时间】: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&lt;Task&gt;.push_back(OverrideTask{}) 将剥离被覆盖的部分并仅保留其 Task 部分。除此之外代码没问题,只要使用std::vector&lt;std::unique_ptr&lt;Task&gt;&gt;就可以了。
  • 你也成为了滥用构造函数以获得副作用的受害者。您永远无法确定是为临时对象、本地对象还是更持久的对象调用构造函数。因此,更好的设计确实将构造函数集中在构造上,并将使用新对象的代码(即负责将所选任务添加到任务列表中)移动到另一个地方。
  • cppcheck 还建议对带有一个参数的构造函数使用显式。

标签: c++ pointers vector


【解决方案1】:

尝试将基指针存储在向量中,而不是像这样。 @Christophe 让我提醒我们存储指针,这意味着 Task 对象 必须活着。另请参阅 @Quimby 关于使用 unique_ptr 而不是 Task * 的说明。

#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::vector<Task *> listOfTasks;
    OverrideTask ot = OverrideTask(&listOfTasks);
    Task t = Task(&listOfTasks);
    for(int i = 0; i < listOfTasks.size(); i++) {
        listOfTasks[i]->Run();
    }
} 

【讨论】:

  • 这似乎有效!我想我确实需要更多地阅读指针,更具体地说,这个“基本指针”概念。谢谢!
  • 放弃投票将不胜感激
  • 点赞当之无愧。但是,您应该警告 OP,当使用任务列表时,此解决方案要求原始任务对象仍然存在。在简单的例子中它是有效的,但是 OP 使用了按值复制的原则,我们不知道意图是不是在某处初始化任务列表,然后调用任务列表。
  • 好点。希望我的文章能让您的评论公正。
  • 完美。对于此处的记录,使用 unique_ptr 和原型模式来克隆添加到列表中的任务的替代代码。但是在构造函数中填充列表的设计对使用虚函数没有帮助;-) ideone.com/GXZ1jX
猜你喜欢
  • 2021-04-17
  • 2014-02-17
  • 2013-09-21
  • 1970-01-01
  • 2010-10-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多