状态模式 C++

2024-01-04

在遵循这里的一些优秀教程之后,我正在尝试创建一个简单的状态模式:http://gameprogrammingpatterns.com/state.html http://gameprogrammingpatterns.com/state.html

我已经完成了当前教程的一半,我正在尝试通过将它们包含在基类中来复制每个状态的静态实例。然而,当涉及到切换状态时,g++ 会抛出这个错误。

   state_test.cpp: In member function ‘virtual void Introduction::handleinput(Game&, int)’:
state_test.cpp:55:16: error: cannot convert ‘Playing*’ to ‘GameState*’ in assignment
    game.state_ = &GameState::play;
                ^

现在,我知道错误涉及指针的转换,但我真的很努力想知道如何修复它。当我跟踪这个人的代码时,我有点期望它能够工作,但是因为他在不断地改变它并试图强化最佳实践,所以我没有他的完整源代码可以跟踪。但是,我觉得在完成本教程的其余部分之前,了解现阶段的代码对我来说很重要。

以下是我创建的代码,试图复制他的状态系统:

#include <iostream>

class Game;
class Introduction;
class Playing;

class GameState
{
public:

    static Introduction intro;
    static Playing play;

    virtual ~GameState() {std::cout << "an undefined GameState has been destroyed" << std::endl;}
    virtual void handleinput(Game& game, int arbitary) {}
    virtual void update(Game& game) {}

};

class Game
{
public:

    Game()
    {}
    ~Game()
    {}

    virtual void handleinput(int arbitary)
        {
            state_->handleinput(*this, arbitary);
        }

    virtual void update()
        {
            state_->update(*this);
        }

//private: 
    GameState* state_;
};

class Introduction : public GameState
{
public:

    Introduction()  
    {
        std::cout << "constructed Introduction state" << std::endl;
    }

    virtual void handleinput(Game& game, int arbitary) 
        {
            if (arbitary == 1)
            game.state_ = &GameState::play;
        }

    virtual void update(Game& game) {}
};

class Playing : public GameState
{
public:
    Playing()   {std::cout << "constructed Playing state" << std::endl;}

    virtual void handleinput(Game& game, int arbitary) 
        {
            if (arbitary == 0)
            game.state_ = &GameState::intro;
        }

    virtual void update(Game& game) {}
};

int main(int argc, char const *argv[])
{
    Game thisgame;

    return 0;
}

有什么想法为什么我的实现无法编译吗?

EDIT:

因此,为了回应之前的辅导,对此我非常感激,我修改了代码。我首先将它们全部放在单独的文件中,但是对于如此少量的测试代码来说,这比它值得的麻烦更多。我只是重写了一个声明类的头文件,然后在 .cpp 文件中定义它们。

这是 .h 文件:

class Introduction;
class Playing;
class Game;
class GameState;

class GameState
{
    public:

    static Introduction intro;
    static Playing play;

    virtual ~GameState();
    virtual void handleinput(Game& game, int arbitary);
    virtual void update(Game& game);

};


class Introduction : public GameState
{
public:

    Introduction();

    virtual void handleinput(Game& game, int arbitary); 

    virtual void update(Game& game);

};

class Playing : public GameState
{
public:
    Playing();

    virtual void handleinput(Game& game, int arbitary);

    virtual void update(Game& game);    
};


class Game
{
public:

    Game();

    ~Game();

    virtual void handleinput(int arbitary);

    virtual void update();

    GameState* state_;

};

这是 .cpp 文件:

#include <iostream>
#include "state.h"


GameState::~GameState() 
    {std::cout << "Exiting Game State Instance" << std::endl;}
void GameState::handleinput(Game& game, int arbitary) 
    {}
void GameState::update(Game& game) 
    {}



Game::Game()
    {}
Game::~Game()
    {}
void Game::handleinput(int arbitary)
        {
            state_->handleinput(*this, arbitary);
        }

void Game::update()
        {
            state_->update(*this);
        }


Introduction::Introduction()    
    {
        std::cout << "constructed Introduction state" << std::endl;
    }

void Introduction::handleinput(Game& game, int arbitary) 
        {
            if (arbitary == 1)
            game.state_ = &GameState::play;
        }

void Introduction::update(Game& game) {}


Playing::Playing()  
        {
            std::cout << "constructed Playing state" << std::endl;
        }

void Playing::handleinput(Game& game, int arbitary) 
        {
            if (arbitary == 0)
            game.state_ = &GameState::intro;
        }

void Playing::update(Game& game) {}



int main(int argc, char const *argv[])
{
    Game mygame;
    return 0;
}

我仍然无法让它发挥作用。之前的错误已经消失,但我正在努力访问“简介”的静态实例并在基类内部播放。抛出的错误是:

/tmp/ccH87ioX.o: In function `Introduction::handleinput(Game&, int)':
state_test.cpp:(.text+0x1a9): undefined reference to `GameState::play'
/tmp/ccH87ioX.o: In function `Playing::handleinput(Game&, int)':
state_test.cpp:(.text+0x23f): undefined reference to `GameState::intro'
collect2: error: ld returned 1 exit status

我以为我已经搞砸了!太沮丧了!

我应该补充一点,RustyX 提供的答案确实可以编译,但是我必须将“播放”和“介绍”的实例移到类定义之外,然后我就不能再将它们设置为静态,我相信这很重要因为我只需要每个实例一个实例,并且我希望它们尽早初始化。


问题是编译器从上到下读取文件。在包含的行

game.state_ = &GameState::play;

他还是不知道Playing继承自GameState。它只知道Playing是一个稍后将声明的类。

您应该将类​​声明与方法实现分开。首先是所有类声明,然后是方法实现。在更大的项目中,您可以将它们全部拆分为单独的 *.h 和 *.cpp 文件,并且这种排序会自然发生。

缩短的示例:

class Playing : public GameState
{
public:
    Playing();

    virtual void handleinput(Game& game, int arbitary);

    virtual void update(Game& game);
};

// Declarations of other classes...


Playing::Playing() {
    std::cout << "constructed Playing state" << std::endl;
}

void Playing::handleinput(Game& game, int arbitrary) {
    if (arbitary == 0)
        game.state_ = &GameState::intro;
    }
}

void Playing::update(Game& game) {
}

您可以在类声明中保留一些方法。通常,如果方法很小,可以从内联中受益并且不存在这种循环依赖问题,则可以这样做。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

状态模式 C++ 的相关文章

随机推荐

  • boost::flat_map 及其与 map 和 unordered_map 相比的性能

    编程中的常识是 由于缓存命中 内存局部性可以大大提高性能 我最近发现boost flat map这是基于矢量的地图实现 它似乎并不像典型的那样受欢迎map unordered map所以我没能找到任何性能比较 它的比较如何 它的最佳用例是什
  • 递归地从 XML 中删除空节点

    我想从 XML 元素中删除空节点 该 xml 是由供应商生成的 我无法控制 xml 的生成 但由于 XML 几乎没有空节点 我需要递归删除这些空节点 这个 xml 是从 OMElement 获取的 我使用 XMLUtils 1 从这个对象获
  • 在 Java 中转换 StAX 源

    我有一些代码 例如 XMLInputFactory xif XMLInputFactory newInstance TransformerFactory tf TransformerFactory newInstance org apach
  • 使用 ffmpeg 合并视频

    我尝试过这个命令 ffmpeg i concat 10 mov 11 mov codec copy out mov输出文件 out mov 仅显示第一部电影 10 mov 中的内容 谷歌搜索了几个小时并尝试了很多东西但没有任何效果 我希望在
  • spring boot cloud eureka windows 10 eureka 在最新的 docker 升级后返回 host.docker.internal 作为客户端主机名

    Spring Boot Cloud Disovery 问题 在 Windows 10 上进行 docker 升级后 Eureka 主机名出现问题 注意 docker 不托管 spring 服务 仅托管 mariadb rabbitmq 和
  • cudamemcpyasync 和流行为理解

    我有下面所示的简单代码 它什么也不做 只是使用流将一些数据从主机复制到设备 但在运行 nvprof 后我很困惑 因为 cudamemcpyasync 确实是异步的并且对流的理解 include
  • Discord4J:不存在类型变量 R 的实例,因此 void 符合 Mono

    我有以下错误no instance s of type variable s R exist so that void conforms to Mono
  • 使用 Lodash 删除数组中的元素

    我有这个数组 var fruits Apple Banana Orange Celery 我用Lodash的remove像这样 remove fruits function fruit return fruit Apple Banana O
  • 错误:输入网格不是有效的网格

    我有个问题 所以我有一个 XxYxZ 10x5x20 的 3D 矩阵 我想在等值面的帮助下绘制这个矩阵 因此 首先我需要创建一个网格 但是当我说时 第一个问题就出现了 X Y Z meshgrid 1 10 1 5 1 20 我得到一个 5
  • 如何使用 Kotlin 在 Android 中动态添加按钮

    如何使用 Kotlin 在 Android 中动态添加按钮 我是 Kotlin 新手 请帮忙 您可以通过调用按钮的构造函数来动态创建按钮 var myButton Button this 这 将是活动
  • 解析 FlightRadar24 和 JSOUP

    大家好 我想在 Flightradar24 com 上解析航班 我尝试过 JSOUP 和 Android 但结果为空 http postimg org image 6hdmp4hgv http postimg org image 6hdmp
  • Docker-compose 与 podman 一起使用?

    如何在 podman 中使用 docker compose 文件 这个例子 version 3 7 services gitea image gitea gitea latest environment DB TYPE postgres D
  • 源代码保护

    当您使用 Visual Studio 2010 编译要发布的程序时 是否有任何高级方法可以使您的程序反编译为源代码 在编译之前有什么方法可以用来加密源代码吗 默认情况下 Visual Studio 不会应用任何形式的增强功能 也不会修改除所
  • 从 JUnit 单元测试设置 android.location.Location 对象的参数

    我正在尝试对接收 android location Location 对象的函数进行单元测试 但我阻止了 因为我无法为位置对象设置参数 Test public void testLocation Location location new
  • Ubuntu 11.04 上的 Rails 3.1 通过 RVM - 未初始化的常量 Psych::Syck

    gem install rails pre ERROR While executing gem NameError uninitialized constant Psych Syck 我似乎找不到任何有关如何解决此问题的信息 还有其他人遇到
  • Flutter webview 文本输入被软键盘隐藏

    我正在 Android 上进行测试 我将验证它在 iOS 上是否相同 我的问题是 当我有一个显示条纹结帐页面的网页视图 并且我点击那里的文本条目以输入靠近底部 邮政编码 的内容时 虚拟键盘会覆盖网页视图 即使在网页视图 看起来 webvie
  • tkinter 中带有 matplotlib 图的弹出窗口

    当我在 tkinter 窗口中插入 matplotlib 图形时 当我启动程序时 会出现额外的弹出窗口 它们不会影响我的 GUI 的功能 但有点烦人 我已经编写了一个显示问题的基本脚本 我通过 Spyder 运行这个 import tkin
  • 如何访问 StreamBuilder 中的多个流?

    我尝试过做一个新的StreamBuilder在我的初始流的构建器内 虽然我没有收到任何错误 但它似乎也不起作用 这可以吗 基本上 我正在访问 Firebase 中的根集合 该集合包含两个文档 我需要每个文档的数据 因为我正在构建一个包含来自
  • 从巨大(>200MB)数组文件中加载随机对象,而不加载整个数组

    我正在构建一个静态 Angular 网站 其数据基于包含超过 200 000 个 JSON 对象的巨大数组中的 1000 个随机对象 我将大量的 JSON 对象以文本形式存储在网上的某个地方 例如 Github 或 Dropbox 并且文本
  • 状态模式 C++

    在遵循这里的一些优秀教程之后 我正在尝试创建一个简单的状态模式 http gameprogrammingpatterns com state html http gameprogrammingpatterns com state html