引用运算符和shared_ptr C ++ 11的误解

时间:2014-09-29 11:11:27

标签: c++ state shared-ptr

我试图升级我的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()
{

}

1 个答案:

答案 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将始终在访问之前检查其目标是否存在。