vector.erase错误,无法删除不完整类型

时间:2017-07-26 16:41:18

标签: c++ pointers vector actor incomplete-type

好吧所以我正在尝试创建一个Actor-Behavior系统,而我在使用不完整的类型时遇到了一些麻烦,基本上,当我试图杀死一个Actor时,它告诉我类Actor是一个不完整的类型。 / p>

所以我的结构如下:

Planet-> Vector of all Actors
Actor-> Vector of all Behaviors
Behaviour-> Game Logic

首先,我们有Behavior类,它引用了它的actor(将它添加到其集合中的actor),一个保存其类型的字符串,以及用于游戏逻辑的函数:init(在启动时调用),以及tick(称为每帧):

class Actor;

class Behaviour
{
  protected:
    Actor* actor;
  public:
    string type;
    Behaviour();
    ~Behaviour();
    virtual void Init(); // virtual because every component needs to override them
    virtual void Tick();
}

然后我们有了Actor类,它包含一个指向其所有行为的唯一指针的向量,一个指向它的Planet的指针,一个唯一的id,一个名称和游戏逻辑函数,用于遍历所有行为并执行游戏逻辑!

// Actor.h
class Planet;

class Actor
{
  private:
    unsigned id;
    string name;
    vector< unique_ptr< Behaviour > > allBehaviours;
  protected:
    Planet* planet;
  public:
    Actor();
    ~Actor();
    void Init(); // Go through all the behaviors and call their Inits and Ticks
    void Tick();

    template <typename T, typename ...Args>
    void AddBehaviour(Args && ...args); // Creates and adds a new Behaviour of type T to the allBehaviours vector

    template <typename T>
    T& GetBehaviour(std::string type); // Loops through all the Behaviours, and returns the Behaviour whose type is the same as type

// Actor.cpp

#include "Planet.h"
#include "Behaviour.h"
#include "Actor.h"

// Implement Functions

那是Actor.h,Actor.cpp实现了那些函数,包括Planet.h然后是Behaviour.h然后是Actor.h!

现在,Planet类包含一个指向其所有Actors的唯一指针的向量,一个名称以及一个用于其Actors的唯一id生成器:​​

// Planet.h

class Actor;

class Planet
{
    private:
      unsigned idCounter = 0;
      string name;
      vector< unique_ptr< Actor > > allActors;
    public:
      unsigned GetNewID();
      void Init();
      void Tick(); // Used to loop through all the Actors

      void AddActor(Actor* newActor); // adds a new Actor to the list of all Actors
      void KillActor(int id); // loops through all the Actors and when it finds an Actor whose unique id is matching the id variable it erases it from the allActors vector

}

// Planet.cpp

#include "Public.h"
#include "Actor.h"
#include "Planet.h"

    Planet::KillActor(int id){
        unsigned i = 0;
        for (auto& a : allActors) {
            if (a->GetID() == id)
                allActors.erase(allActors.begin() + i);
            i++;
        }
    }

    // Other Functions

我还有一个Public.h文件,其中包含iostream,内存,向量等内容!但是不包括我创建的文件!

还有一个名为Win的类,它有一个unique_ptr&lt;的集合。行星&gt; 在Public.h中有一个名为win的公共变量(包含在任何地方),每次构建一个Planet时它都被推送到该集合,而Win类有一个指向最后构建的Planet的指针,所以每次一个Actor都是构造,这一行被称为:

{
 // other stuff
 win.GetCurrentPlanet()->AddActor(this); 
}

我测试了这个结构并且它运行成功,我可以有多个行星并从一个跳到另一个,指向Actors的指针没有问题,指向行为的指针也可以正常工作!

现在的问题在于,当我调用KillActor函数时,它正确地遍历所有Actors,它找到了我要杀死的Actor然后当我调用擦除该Actor时它将我发送到文件内存,并告诉我我的程序触发了一个断点:

void operator()(_Ty *_Ptr) const _NOEXCEPT
    {   // delete a pointer
    static_assert(0 < sizeof (_Ty),
        "can't delete an incomplete type");
    delete _Ptr; // Here is the breakpoint, it is trying to delete the Actor I inputed 
    }
};

我不明白为什么它会给我这个错误,我很确定我有一个非常可靠的包括和前向声明结构。

编辑1:

好的,所以我做了一个测试,我禁用了Tick函数(它现在没有做任何事情),我正在调用KillActor:

int main() {

    Planet b = Planet("B");

    Actor bactor = Actor();

    bactor.AddBehaviour<TestA>();

    b.KillActor(0); // This still results in the same incomplete type error!

    do
    {
        win.changed = false;
        win.GetCurrentPlanet()->Init();
        while (win.gameRunning)
        {
            win.Tick();
            //win.GetCurrentPlanet()->Tick(1);
            if (win.changed)
                break;
        }
    } while (win.changed);

    win.Quit();

    return 0;
}

1 个答案:

答案 0 :(得分:0)

您无法从仍在迭代的容器中删除。你的killActor函数是未定义的行为。尝试删除删除,如here

您有虚拟功能,但没有虚拟析构函数。解决它。