我试图升级我的C ++知识,需要帮助理解一些带有引用指针和shared_ptr
的构造。
我有这样的结构:
IState *m_Loader;
void CStateManager::AttachState(E_STATE _estate, const IState &_state)
{
switch(_estate)
{
case STATE_LOADER:
m_Loader = _state;
break;
}
}
编译器告诉我,它无法将" Const IState
转换为IState*
" - 我怎么能保存对象,以后可以使用它?我试图摆脱旧C语言的指针并使用现代C ++。
第二个问题是我如何使用shared_ptr
来实现状态模式?我认为使用shared_ptr
并且可能需要weak_ptr
是不可靠的,但我仍然无法想象如何实现这样的事情。
这里有完整的源代码,以了解我尝试实施的内容。
#pragma once
#include <memory>
class IState;
class IStateManager
{
public:
enum E_STATE
{
STATE_LOADER,
STATE_MENU,
STATE_GAME,
STATE_EXIT
};
virtual void SwitchState(E_STATE _estate) = 0;
virtual void AttachState(E_STATE _estate, const IState &_state) = 0;
virtual void Update() = 0;
public:
virtual ~IStateManager() {}
};
class IState
{
public:
virtual void Enter(const IStateManager &_statemgr) = 0;
virtual void Exit() = 0;
virtual void Sleep() = 0;
virtual void Update() = 0;
public:
virtual ~IState() {}
};
class CStateManager: public IStateManager
{
public:
void SwitchState(E_STATE _estate);
void AttachState(E_STATE _estate, const IState &_state);
void Update();
~CStateManager();
private:
IState *m_Loader;
IState *m_Menu;
IState *m_Game;
IState *m_Exit;
};
;
void CStateManager::SwitchState(E_STATE _estate)
{
}
void CStateManager::AttachState(E_STATE _estate, const IState &_state)
{
switch(_estate)
{
case STATE_LOADER:
m_Loader = _state;
break;
case STATE_MENU:
break;
case STATE_GAME:
break;
case STATE_EXIT:
break;
}
}
void CStateManager::Update()
{
}
CStateManager::~CStateManager()
{
}
答案 0 :(得分:0)
您最关心的是您引用的对象的生命周期,无论您使用引用,原始指针还是shared_ptr
,您都可能遇到麻烦,例如:
CStateManager test()
{
CStateManager result;
IState localIState;
result.AttachState( CStateManager::STATE_LOADER, localIState );
return result;
}
int main()
{
CStateManager badLoader = test();
return 0;
}
在main
函数中,如果访问badLoader::m_Loader
,则会出现段错误,因为m_Loader是指向不再存在的内存位置的指针。如果m_Loader
是参考,或者甚至是shared_ptr
,那么同样的事情显然也是如此。
如何使用m_Loader
作为weak_ptr
来避免段错误。所以你的代码会改变如下:
std::weak_ptr< IState > m_Loader;
void CStateManager::AttachState(E_STATE _estate, std::weak_ptr< IState > _state)
{
switch(_estate)
{
case STATE_LOADER:
m_Loader = _state;
break;
}
}
在调用函数中,您还必须更改创建localIState
的方式:
CStateManager test()
{
CStateManager result;
std::shared_ptr< IState > localIState( new IState );
result.AttachState( CStateManager::STATE_LOADER, localIState );
return result;
}
如果您访问badLoader::m_Loader
中的main
,这将保护您免受segfaulting攻击,因为std::weak_ptr
将始终在访问之前检查其目标是否存在。