2

I have a problem with this code - this is taskData:

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

and there is a problem:

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

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;
    };
}

Task:

#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;
    };
}

and the error is:

Error C2259 'mc::Task': cannot instantiate abstract class

I really don't know why I get this error. When I remove this line:

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

it works without problems :/

MLavoie
  • 9,671
  • 41
  • 36
  • 56
mvxxx
  • 115
  • 9

3 Answers3

6

The culprit is std::vector<Task> – you can't create a vector of Task since Task is abstract.

You need to use a vector of pointers.

molbdnilo
  • 64,751
  • 3
  • 43
  • 82
  • When i change it to shared_prt, there is the same problem taskData.emplace(pi::enumerations::taskManager::taskCategory_t::SECURITY, std::vector>{std::make_shared(FirefightingTask())}); – mvxxx Mar 18 '17 at 09:57
  • @mvxxx YOu are using `make_shared` wrong. Right now you are trying to create `Task` object (abstract) from temporary `Fi‌​refightingTask`. – Revolver_Ocelot Mar 18 '17 at 10:27
  • i have tried it: taskData.emplace(pi::enumerations::taskManager::taskCategory_t::SECURITY, std::vector>{std::make_shared(FirefightingTask())}); and i got this error: Error LNK2019 unresolved external symbol "public: __thiscall mc::FirefightingTask::FirefightingTask(unsigned char,unsigned char,class mc::NPC *)" (??0FirefightingTask@mc@@QAE@EEPAVNPC@1@@Z) referenced in function "public: static void __cdecl mc::TaskManager::loadData(void)" (?loadData@TaskManager@mc@@SAXXZ) – mvxxx Mar 18 '17 at 10:56
0

std::vector is not allowed, as it would create objects of class "Task" which is abstract because of your "act" method. Note that your solution from the other answer with std::make_shared won't work as well, since make_shared tries to create an instance of "Task". You should try to create your firefightingTask with make_shared< FirefightingTask>().

An other note: you are using Task as virtual base class, so you should consider a virtual destructor.

0

Task is abstract, so there cannot be instances of it. A std::vector contains and owns instances of its value type. A std::vector of an abstract type is therefore impossible and doesn't make sense. You cannot contain and own something which cannot exist. That's the fundamental difference to vectors such as std::vector<int>, std::vector<std::string> or std::vector<FirefightingTask>.

It doesn't help that the dynamic type of the objects inside of your vector is supposed to be something else (i.e. FirefightingTask). Only the static type is relevant for the compiler.

Pointers, however, can exist. They meet all conditions necessary to put them into a std::vector. What they point to is irrelevant for std::vector. The idea is that they statically point to Task and dynamically to FirefightingTask instances (or instances of other concrete subclasses).

Now, raw pointers should typically not be handled manually, because that's verbose and error-prone. Fortunately, C++ offers smart-pointer classes to prevent low-level memory-management mistakes. std::unique_ptr should be your default choice when it comes to smart pointers. Here is a simple example based loosely on your code:

#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>());
}
Christian Hackl
  • 27,051
  • 3
  • 32
  • 62
  • This make unresolved :/ Error LNK2019 unresolved external symbol "public: __thiscall mc::FirefightingTask::FirefightingTask(unsigned char,unsigned char,class mc::NPC *)" (??0FirefightingTask@mc@@QAE@EEPAVNPC@1@@Z) referenced in function "public: __thiscall std::_Ref_count_obj::_Ref_count_obj<>(void)" (??$?0$$V@?$_Ref_count_obj@VFirefightingTask@mc@@@std@@QAE@XZ) – mvxxx Mar 18 '17 at 12:40
  • @mvxxx: That's doubtful, because my code contains neither `NPC`, nor a `FirefightingTask` constructor with four parameters. – Christian Hackl Mar 18 '17 at 12:43
  • @mvxxx: `_Ref_count_obj` also sounds a lot like `std::shared_ptr`, not `std::unique_ptr`, because the former is reference-counted whereas the latter is not. – Christian Hackl Mar 18 '17 at 12:44
  • I know, i am using shared_ptr because i need it, but it does not solve my problem – mvxxx Mar 18 '17 at 14:57
  • @mvxxx: Why do you suddenly need `std::shared_ptr`? – Christian Hackl Mar 18 '17 at 14:59
  • Because i have got in NPC another vector which containts some elements of this vector: std::vector> skills; – mvxxx Mar 18 '17 at 15:04
  • @mvxxx: It seems your new problem has nothing to do with the original question anymore. – Christian Hackl Mar 18 '17 at 15:07