【问题标题】:cannot instantiate abstract class c++无法实例化抽象类 c++
【发布时间】:2025-12-13 14:50:02
【问题描述】:

我对这段代码有疑问 - 这是 taskData:

static std::map<int8_t, std::vector<Task>> taskData;

还有一个问题:

taskData.emplace(pi::enumerations::taskManager::taskCategory_t::SECURITY, std::vector<Task>{FirefightingTask()});

消防任务:

#pragma once

#include "Task.hpp"

namespace mc
{
    class FirefightingTask :public Task
    {
    public:

        FirefightingTask( uint8_t category = 0, uint8_t kind = 0, NPC* npc = nullptr );

        virtual bool act() override;
    };
}

任务:

#pragma once

#include "engine/Config.hpp" 

#include <queue>

class NPC;

namespace mc
{
    //Task
    //Represents a task for AI object
    class Task
    {

    public:
        Task(uint8_t category = 0, uint8_t kind = 0, NPC* npc = nullptr );

        uint8_t GetCategory()
        {
            return category;
        }

        uint8_t GetKind()
        {
            return kind;
        }

        bool operator==( const Task& second )
        {
            return this->kind == second.kind;
        }

        bool inProgress()
        {
            return doing;
        }

        virtual bool act() = 0;

    private:

        bool doing;

        const int8_t category;

        const int8_t kind;

        NPC* owner;
    };
}

错误是:

错误 C2259 'mc::Task':无法实例化抽象类

我真的不知道为什么会出现这个错误。当我删除这一行时:

        taskData.emplace(pi::enumerations::taskManager::taskCategory_t::SECURITY,std::vector<Task>{FirefightingTask()});

它可以正常工作:/

【问题讨论】:

  • 你需要std::vector&lt;Task*&gt;或(更好)std::vector&lt;std::shared_ptr&lt;Task&gt;&gt;std::vector&lt;std::unique_ptr&lt;Task&gt;&gt;
  • 相关阅读:What is object slicing?
  • 当我把它改成 shared_prt 时,也有同样的问题 taskData.emplace(pi::enumerations::taskManager::taskCateg‌​ory_t::SECURITY, std::vector<:shared_ptr>>{std::make_shared(Fi‌​refightingTask())});

标签: c++ class abstract


【解决方案1】:

罪魁祸首是std::vector&lt;Task&gt;——你不能创建Task的向量,因为Task是抽象的。

您需要使用指针向量。

【讨论】:

  • 当我把它改成shared_prt时,同样的问题taskData.emplace(pi::enumerations::taskManager::taskCategory_t::SECURITY, std::vector<:shared_ptr> >{std::make_shared(FirefightingTask())});
  • @mvxxx 你用错了make_shared。现在你正试图从临时的Fi‌​refightingTask 创建Task 对象(抽象)。
  • 我试过了:taskData.emplace(pi::enumerations::taskManager::taskCategory_t::SECURITY, std::vector<:shared_ptr>>{std::make_shared(消防任务())});我收到了这个错误:错误 LNK2019 未解析的外部符号“公共:__thiscall mc::FirefightingTask::FirefightingTask(unsigned char,unsigned char,class mc::NPC *)”(??0FirefightingTask@mc@@QAE@EEPAVNPC@1 @@Z) 在函数“public: static void __cdecl mc::TaskManager::loadData(void)”中引用 (?loadData@TaskManager@mc@@SAXXZ)
【解决方案2】:

std::vector 是不允许的,因为它会创建类“Task”的对象,因为你的“act”方法是抽象的。 请注意,您在 std::make_shared 的其他答案中的解决方案也无法正常工作,因为 make_shared 尝试创建“任务”的实例。 您应该尝试使用 make_shared() 创建您的 firefightingTask。

另一个注意事项:您使用 Task 作为虚拟基类,因此您应该考虑使用虚拟析构函数。

【讨论】:

  • 当我尝试 std::make_shared... 我有外部错误
【解决方案3】:

Task 是抽象的,所以不能有它的实例。 std::vector 包含并拥有其值类型的实例。因此,抽象类型的std::vector 是不可能的并且没有意义。你不能包含和拥有不存在的东西。这是与std::vector&lt;int&gt;std::vector&lt;std::string&gt;std::vector&lt;FirefightingTask&gt; 等向量的根本区别。

向量内的对象的 dynamic 类型应该是其他东西(即FirefightingTask)并没有帮助。只有静态类型与编译器相关。

但是,

指针可以存在。它们满足将它们放入std::vector 所需的所有条件。他们指向的内容与std::vector 无关。想法是它们静态指向 Task 并动态指向 FirefightingTask 实例(或其他具体子类的实例)。

现在,通常不应手动处理原始指针,因为这很冗长且容易出错。幸运的是,C++ 提供了智能指针类来防止低级内存管理错误。当涉及到智能指针时,std::unique_ptr 应该是您的默认选择。这是一个基于您的代码的简单示例:

#include <vector>
#include <map>
#include <memory>

struct Task { virtual ~Task() = 0; };
struct FirefightingTask : Task {};
Task::~Task() {}

int main()
{
    std::map<int, std::vector<std::unique_ptr<Task>>> taskData;

    // map an empty vector of Task pointers to key 0:
    taskData.emplace(0, std::vector<std::unique_ptr<Task>>());

    // three times in a row, create a FirefightingTask instance
    // directly inside of the previously empty vector at key 0:
    taskData[0].emplace_back(std::make_unique<FirefightingTask>());
    taskData[0].emplace_back(std::make_unique<FirefightingTask>());
    taskData[0].emplace_back(std::make_unique<FirefightingTask>());
}

【讨论】:

  • 这使得无法解决:/错误 LNK2019 无法解决外部符号“public: __thiscall mc::FirefightingTask::FirefightingTask(unsigned char,unsigned char,class mc::NPC *)” (??0FirefightingTask@mc @@QAE@EEPAVNPC@1@@Z) 在函数“public: __thiscall std::_Ref_count_obj::_Ref_count_obj(void)”(??$? 0$$V@?$_Ref_count_obj@VFirefightingTask@mc@@@std@@QAE@XZ)
  • @mvxxx:这值得怀疑,因为我的代码既不包含NPC,也不包含具有四个参数的FirefightingTask 构造函数。
  • @mvxxx: _Ref_count_obj 听起来也很像std::shared_ptr,而不是std::unique_ptr,因为前者是引用计数的,而后者不是。
  • 我知道,我正在使用 shared_ptr 因为我需要它,但它不能解决我的问题
  • @mvxxx:你为什么突然需要std::shared_ptr