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
的情况一样,那么通过引用传递它可能更快(并且仍然安全) .
本题来自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
的情况一样,那么通过引用传递它可能更快(并且仍然安全) .