byr*_*ice 2 c++ boost shared-ptr
如果我需要阅读很多代码,我很抱歉,如果我可以简化解释请告诉我,如果你想评论我的设计/实践是免费的.
所以我的播放器被删除了两次,我不知道为什么.如果查看调用堆栈,您会看到GameEventManager实际上是在GameState析构函数之前调用Player析构函数,即使GameState是指向Player的指针.我想也许这是因为它还会先破坏矢量,所以它会在矢量中找到Player并试图摧毁它.我不知道为什么它会试图摧毁播放器,因为仍然存在GameState对象所知道的Player的引用.共享指针功能应该阻止播放器被破坏.
也许我会以错误的方式解决这个问题,如果是这样,有人会指出我在这里的最佳做法的正确方向?谢谢
调用堆栈:
 
 
 GameState.h
GameState.h
#ifndef _level
#define _level
#include <vector>
#include "Player.h"
#include <memory>
using namespace std;
class GameState // A representation of the Level/Game/Scene
{
public:
    GameState();
    virtual ~GameState() {}
    //Keep track of the game's state
    //Maybe get rid of the Level class, and make this a class, and move the Level functionality here?
    static void EndGame(const bool & b) { mbEndGame = b; }
    static const bool & EndGame() { return mbEndGame; }
private:
    void SetPlayer(shared_ptr<Player> sptrPlayer) { msptrPlayer = sptrPlayer; }
    static bool mbEndGame;
    shared_ptr<Player> msptrPlayer;
    vector<shared_ptr<Player>> msptrMob; // Representation of all the NPCs in the game. Eventually make a Mob class but for now just use Player
    // shared_ptr<LevelMap> mMap // Representation of what the game looks like visually
    // Renderer // Should the level have the renderer to create the graphics? Or should this be handled by another "GUI Layer" and interact with this layer as little as possible ?
};
#endif
GameState.cpp
#include "stdafx.h"
#include "GameState.h"
bool GameState::mbEndGame(false);
GameState::GameState() : msptrPlayer(NULL)
{
    shared_ptr<Player> sptrPlayer(new Player);
    SetPlayer(sptrPlayer);
}
GameObject.h
#ifndef _game_object
#define _game_object
#include <memory>
// Game Object Classes inherit this so they are registered with GameEventManager.
using namespace std;
class GameObject{
public:
    GameObject();
    virtual ~GameObject() {}
    virtual void Update() = 0;
    virtual void Start() = 0;
};
#endif
GameObject.cpp
#include "stdafx.h"
#include "GameObject.h"
#include "GameEventManager.h"
GameObject::GameObject()
{
    shared_ptr<GameObject> ptr(this);
    GameEventManager::GetGameEventManager()->RegisterGameObject(ptr);
}
Player.h
#ifndef _player
#define _player
#include "GameObject.h"
//A representation of the Player. Used by Level.
class Player : public GameObject
{
public:
    Player();
    virtual ~Player() {}
private:
    virtual void Update();
    virtual void Start();
    int miMaxHealth;
};
#endif
Player.cpp
#include "stdafx.h"
#include "Player.h"
#include "GameState.h"
Player::Player() : miMaxHealth(100) {};
void
Player::Start()
{
}
void
Player::Update() // reimplement GameObject::Update(), which is called by the GameEventManager
{
    --miMaxHealth;
    if (miMaxHealth <= 0)
    {
        GameState::EndGame(true);
    }
}
GameEventManager.h
#ifndef _game_event_manager
#define _game_event_manager
#include "stdafx.h"
#include <memory>
#include <vector>
#include "GameObject.h"
#include "GameState.h"
using namespace std;
class GameEventManager{ 
    //Object which inherit from GameObject are automatically registered with GameEventManager when they are constructed.
    // GameEventManager creates the level object to represent the game, and then runs Start() on all registered GameObjects
    // and then continually runs Update() on all registered game objects until the GameState is set to EndGame.
public:
    virtual ~GameEventManager(){} // This gets called at the end of the program (I guess whne static variables are destroyed), and crashes during vector<shared pointer <GameObject>> destruction, probably because
                                  // Player already destroyed it. So... not sure what to do. If I make it non-static  
    void StartGameEvents(); 
    const static shared_ptr<GameEventManager>& GetGameEventManager();
    const shared_ptr<GameState>& GetLevel();
    void RegisterGameObject(shared_ptr<GameObject> sptrGameObject);
    const shared_ptr<vector<shared_ptr<GameObject>>>& GetRegisteredGameVector() const { return mvecRegisteredGameVector; }
private:
    GameEventManager(); //singleton
    void AddGameObject(shared_ptr<GameObject>);
    shared_ptr<GameState> mLevel;
    shared_ptr<vector<shared_ptr<GameObject>>> mvecRegisteredGameVector; //Reference because shared pointer will double delete otherwise. ~Level() still deletes it but this way I guess it doesn't try to delete again? but...
                                                                        //Now I'm trying it as a shared_ptr, but it's not working. ~Level() still deletes it even though there is a shared pointer to a vector pointing to the Player. Why is ~Level() doing this?
    static shared_ptr<GameEventManager> msptrGameEventManager;
};
#endif
GameEventManager.cpp
#include "stdafx.h"
#include "GameEventManager.h"
#include "GameState.h"
shared_ptr<GameEventManager> GameEventManager::msptrGameEventManager(new GameEventManager);
void
GameEventManager::StartGameEvents()
{
    //run once
    int size = GetRegisteredGameVector()->size();
    vector<shared_ptr<GameObject>> & vecsptrRegisteredGameVector = (*GetRegisteredGameVector());
    for (int i = 0; i < GetRegisteredGameVector()->size(); ++i)
    {
        vecsptrRegisteredGameVector[i]->Start(); //nothing for now 
    }
    //keep running
    while (GetLevel()->EndGame() != true)
    {
        for (int i = 0; i < GetRegisteredGameVector()->size(); i++)
        {
            (*GetRegisteredGameVector())[i]->Update(); //Player's life goes from 100 to zero, see Player::Update
        }
    }
    return; 
    // GameState destructor is called and destroys player for some reason, even though it's still being referenced by the GameEventManager's vector.
}
GameEventManager::GameEventManager() : mvecRegisteredGameVector(new vector<shared_ptr<GameObject>>) , mLevel(NULL) //Instantiating the level before the GameEventManager is fully instantiated causes an infinite recursion.
{
    return;
}
const shared_ptr<GameEventManager>& 
GameEventManager::GetGameEventManager()
{
    if (!msptrGameEventManager)
    {
        msptrGameEventManager.reset(new GameEventManager);
    }
    return msptrGameEventManager;
}
const shared_ptr<GameState>&
GameEventManager::GetLevel()
{
    if (!mLevel)
    {
        mLevel.reset(new GameState);
    }
    return mLevel;
}
void 
GameEventManager::RegisterGameObject(shared_ptr<GameObject> sptrGameObject)
{
    GetGameEventManager()->AddGameObject(sptrGameObject);
}
void
GameEventManager::AddGameObject(shared_ptr<GameObject> sptrGameObject)
{
    GetRegisteredGameVector()->push_back(sptrGameObject);
}
GameObject::GameObject()
{
    shared_ptr<GameObject> ptr(this);
    GameEventManager::GetGameEventManager()->RegisterGameObject(ptr);
}
在ptr与任何其他在此功能不会共享所有权shared_ptr独立构造,就像在声明的一个shared_ptr<Player> sptrPlayer(new Player);.shared_ptr从原始指针创建两个而不是复制第一个指针通常会导致双重删除.
相反,你可以做这样的事情:
class GameObject :
    public std::enable_shared_from_this<GameObject>
{
protected:
    GameObject(); // creates the original shared_ptr
    virtual ~GameObject();
};
class Player : public GameObject
{
public:
    static std::shared_ptr<Player> create();
private:
    Player() : GameObject() {}
    virtual ~Player() {}
};
std::shared_ptr<Player> Player::create() {
    return dynamic_pointer_cast<Player>((new Player)->shared_from_this());
}