【发布时间】:2018-01-02 03:01:36
【问题描述】:
好的,所以我正在尝试创建一个 Actor-Behaviour 系统,但我遇到了一些不完整类型的问题,基本上,当我尝试杀死一个 Actor 时,它告诉我类 Actor 是一个不完整类型。
所以我的结构如下:
Planet-> Vector of all Actors
Actor-> Vector of all Behaviors
Behaviour-> Game Logic
首先,我们有一个 Behavior 类,它有一个对它的actor(将它添加到它的集合中的actor)的引用,一个保存它的类型的字符串,以及用于游戏逻辑的函数:init(在启动时调用)和滴答(每帧调用):
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 类,它包含指向其所有行为的唯一指针向量、指向其行星的指针、唯一 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 的集合 并且在 Public.h 中有一个名为 win 的公共变量(包含在任何地方),每次构建一个 Planet 时,它都会被推送到该集合,并且 Win 类有一个指向最后一个构建的 Planet 的指针,所以每次 Actor 都是构造,这条线被调用:
{
// other stuff
win.GetCurrentPlanet()->AddActor(this);
}
我已经测试过这个结构并且它工作成功,我可以拥有多个行星并从一个跳转到另一个,指向 Actors 的指针可以正常工作,指向 Behaviors 的指针也可以正常工作!
现在问题出在我调用 KillActor 函数时,它会正确循环所有 Actor,找到我想要杀死的 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;
}
【问题讨论】:
-
Actor 它给了我“无法删除不完整类型”错误!请复制粘贴所有错误文本,不要解释它,然后尝试缩短它。
-
您无法从仍在迭代的容器中擦除。您的 killActor 函数是未定义的行为。尝试像 here 一样擦除删除。
-
@Hello 由于它触发了一个断点,这意味着它显然是一个运行时问题,而不是编译时问题,您是否使用调试器来调查调用堆栈,相关的值变量等?
-
“不能删除不完整的类型”部分是一个红鲱鱼。它在一个静态断言中;如果失败,您的程序将拒绝编译。你编译得很好,但是遇到了运行时错误。在运行时,没有不完整的类型。
-
@DanielH 我明白了,谢谢你的信息,你也看到我的最后编辑了吗?这让我认为这与迭代无关!我会尝试虚拟析构函数,看看会发生什么!
标签: c++ pointers vector actor incomplete-type