gpt4 book ai didi

c++ - 堆栈分配类发生不需要的析构函数调用 - C++

转载 作者:行者123 更新时间:2023-11-30 02:03:04 25 4
gpt4 key购买 nike

在 Game 类函数中,我将 Boundary 类分配给堆栈

void Game::loadContent()
{
Boundary b(this, body);
}

边界类有一个指向主游戏类的指针和一个指向刚体的指针。我不确定我是否应该为每个人使用引用?出于稍后解释的原因,此处的一些清晰度会有所帮助。

class Boundary : public DynamicEntity
{
public:
Boundary(Game *game, btRigidBody *body);
~Boundary(void);

// Override functions
virtual void draw(float dt);
virtual glm::vec3 getPosition();
virtual void update(float dt);
};

DynamicEntity 类在其析构函数中分配主体并处理指针删除。

class DynamicEntity : public Entity
{
public:
virtual ~DynamicEntity(void);

virtual void draw(float dt) = 0;
btRigidBody* getBody();
glm::vec3 getPosition() = 0;
virtual void update(float dt) = 0;

protected:
explicit DynamicEntity(Game *game, btRigidBody *body);
btRigidBody *m_body;
};

DynamicEntity.cpp 析构函数

DynamicEntity::~DynamicEntity(void)
{
m_game->m_dynamicsWorld->removeRigidBody(m_body);

delete m_body;
}

DynamicEntity 派生自所有名为 Entity 的游戏对象的基类

实体.h

class Entity
{
public:
// Make destructor virtual as this is a base class
virtual ~Entity(void);

virtual void draw(float dt) = 0;
int getID();
virtual glm::vec3 getPosition() = 0;
virtual void update(float dt) = 0;

protected:
explicit Entity(Game *game); // Abstract base constructor

Game *m_game;
int m_id; // Unique ID
};

虽然我无法在此类的析构函数中对 Game 类指针调用 delete,但这就是为什么我不确定作为指针传递是否是正确的方法(而不是引用)?

Entity::~Entity(void)
{
// Derived class destructors are called first
delete m_game; // ERROR
}

Entity 类添加了一个指向自身的指针,可以通过 Game 类中的列表访问该指针(对于迭代和调用主 Game 类中的 Entity 函数很有用)。

Entity::Entity(Game *game) 
: m_game(game), // Initialise members
m_id(m_game->g_idGenerator->generateNewID()) // Generate unique ID
{
m_game->m_entities.push_back(std::shared_ptr<Entity>(this));
}

我遇到的主要问题是,一旦 Game::loadContent() 方法完成,就会为 Entity 类调用析构函数。这会破坏存储在列表中的 *shared_ptr*,并且在尝试调用任何虚拟方法时会发生错误。

我希望边界指针一直存在,直到我说删除。有没有办法在不将边界分配给堆的情况下执行此操作?

编辑

响应使用const& Game的建议

看来我必须将实体 header 更改为以下内容

实体.h

#pragma once

#include <glm\glm\glm.hpp>

#include "Game.h"

// Forward declarations
class Game;

class Entity
{
public:
// Make destructor virtual as this is a base class
virtual ~Entity(void);

// '= 0' means pure virtual function (like 'abstract' in C#)
// This means they do not have to be declared in the source file '.cpp'
virtual void draw(float dt) = 0;
int getID();
virtual glm::vec3 getPosition() = 0;
virtual void update(float dt) = 0;

protected:
explicit Entity(const Game &game); // Abstract base constructor

Game m_game;
int m_id; // Unique ID
};

Game m_game 不是将 Game 类的实例分配到堆栈吗?如果它表示引用,应该如何在标题中声明?

编辑 2

如果我在基类 Entity 中存储对 Game 类的 protected 引用 const Game &m_game 我似乎无法在派生中访问 Game 类 g_wireShapeDrawer 的全局成员类。

class Game
{
public:
GL_WireShapeDrawer g_wireShapeDrawer;

Game(void);
~Game(void);

void init();
void draw(float dt);
void handleInput(float dt);
void loadContent();
void update(float dt);
};

例如,当我尝试访问派生边界类源的绘制方法中的全局成员时出现以下错误

void Boundary::draw(float dt)
{
m_game.g_wireShapeDrawer.drawPlane(glm::vec3(0, 1, 0), 0.0f, glm::vec4(1, 1, 1, 1));
}

error C2662: 'GL_WireShapeDrawer::drawPlane' : cannot convert 'this' pointer from 'const GL_WireShapeDrawer' to 'GL_WireShapeDrawer &

这是为什么?

最佳答案

永远不要从任何Entity 或派生类中删除Game 对象。它应该是应用程序关闭前最后要释放的东西之一。

您应该将它作为 Game& 传递给您的 Entity 类。为什么?因为您只有一个 Game 实例,所以无需重置它指向的内容,并且它始终应该是有效的(因为游戏会在Entity 对象做)。

另一种选择是在您的 Game 类中实现单例模式,并像这样访问它 Game::GetInstance().m_dynamicsWorld->removeRigidBody( m_body);

根据您的编辑,您可以使用初始化列表创建一个实体。这样你就可以存储 const 成员,像这样:

class Entity
{
protected:
explicit Entity(Game &game) : m_game(game) {}
private:
Game& m_game;
}

关于c++ - 堆栈分配类发生不需要的析构函数调用 - C++,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12502988/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com