c++如何知道在状态模式中向何处转发声明

c++ how to know where to forward declare in state pattern

本文关键字:何处 转发 声明 模式 何知道 状态 c++      更新时间:2023-10-16

这个问题来自这个问题。我试图实现一个shared_ptr到容器(游戏)的状态模式。

然而,我有一个循环包含的问题,需要向前声明。

我代码:

Game.h

#pragma once
#include <memory>
#include "BaseState.h"
class Game : public std::enable_shared_from_this<Game>
{
private:
    std::shared_ptr<BaseState> currentState;
public:
    Game();
    void switchState(std::shared_ptr<BaseState> nextState);
    void doSomething(char);
    void runState();
};

cpp

#include "stdafx.h"
#include <iostream>
#include "Game.h"
#include "SomeState.h"
Game::Game()
{
    currentState = std::make_shared<SomeState>();
}
void Game::switchState(std::shared_ptr<BaseState> nextState)
{
    currentState = nextState;
}
void Game::doSomething(char c)
{
    std::cout << "Game : " << c;
}
void Game::runState()
{
    currentState->handleCommand(shared_from_this());
}

BaseState.h

#pragma once
#include <memory>
#include "Game.h"
class BaseState
{
public:
    virtual void handleCommand(std::shared_ptr<Game>) = 0;
};

SomeState.h

#pragma once
#include "BaseState.h"
class SomeState :
    public BaseState
{
public:
    // Inherited via BaseState
    virtual void handleCommand(std::shared_ptr<Game>) override;
};

cpp

#include "stdafx.h"
#include "SomeState.h"
void SomeState::handleCommand(std::shared_ptr<Game> game)
{
    game->doSomething('S');
}

我读了其他关于前向声明的问题,但仍然不明白。

What I try;

forward declare BaseState in Game,代码编译但抛出错误。

ConsoleApplication1.exe中0x73E9DAE8的未处理异常:Microsoft c++异常:std::bad_weak_ptr在内存位置0 x00bbf5d4。

正向声明GameBaseState中。Dosnt compile给出了未定义类型错误的使用,也是

'doSomething':不属于"std::要查看"

这是合乎逻辑的因为在编译时game没有doSomething函数因为forward声明像;

class Game;

我如何决定在哪里转发声明另一个类,是否有任何逻辑步骤,或者我应该选择一个并解决选择产生的问题?

您不需要在BaseState.h中添加#include <Game.h>,您可以简单地向前声明它

class Game;

这样做是因为BaseState声明不需要知道Game的内容。所以你先尝试的是可以的。Game.h中的#include <BaseState.h>也是如此。将其替换为BaseState的前向声明。

std::bad_weak_ptr异常是由其他原因引起的。具体来说,您可能错过了关于shared_from_this的小细节,它表示

只允许在先前共享的对象上调用shared_from_this对象,即在由std::shared_ptr管理的对象上。否则,行为未定义

(来自c++ 17) std::bad_weak_ptr被抛出weak_this)的Shared_ptr构造函数

通常可以通过将对象实例化为shared_ptr:

来解决这个问题。
int main() {
    auto myGame = std::make_shared<Game>();
    . . .
    myGame->runState();
    . . .
}

编辑

请记住,使用shared_ptr有一定的成本。一般来说,如果您知道指向对象总是比使用它的函数调用更长寿,就像您的BaseState::handleCommand的情况一样,那么通过引用传递它可能会更快(并且仍然安全)。