C ++如何知道在状态模式中转发声明的位置

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

本题来自this题。 我正在尝试使用 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');
}

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

我试过的;

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

Unhandled exception at 0x73E9DAE8 in ConsoleApplication1.exe: Microsoft C++ exception: std::bad_weak_ptr at memory location 0x00BBF5D4.

BaseState中转发声明Game。 Dosnt编译给出未定义类型错误,也

'doSomething': is not a member of 'std::shared_ptr'

这是合乎逻辑的,因为在编译时游戏没有 doSomething 函数,因为 forward 声明为 like;

class Game;

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

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

class Game;

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

的前向声明

std::bad_weak_ptr 异常是由于其他原因造成的。具体来说,您可能遗漏了关于 shared_from_this 的小细节,它表示

It is permitted to call shared_from_this only on a previously shared object, i.e. on an object managed by std::shared_ptr. Otherwise the behavior is undefined

(from C++17) std::bad_weak_ptr is thrown (by the shared_ptr constructor from a default-constructed weak_this)

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

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

编辑

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