当被子类访问时超类成员指针变为空

Superclass member pointer becomes null when accessed by subclass

我最近看了很多书,决定尝试实现一个简单的状态模式,看看它们是如何组合在一起的。

但是,我 运行 遇到了一个以前从未遇到过的问题:场景的子类 (Start) 似乎没有继承超类构造函数设置的指针值。

这是代码

//main.cpp
#include "Game/game.hpp"
#include "Game/Scene/start.hpp"

int main()
{
    Game::Game *g = new Game::Game;
    Game::Scene::Start *s = new Game::Scene::Start(g);
    g->set_scene(s);
    g->loop();
    
    delete g;
    
    return 0;
}
//Game/Scene/Scene.hpp
#ifndef GAME_SCENE_H
#define GAME_SCENE_H

namespace Game
{
    class Game;
    namespace Scene
    {
        class Scene
        {
        public:
            Scene(Game *game);
            virtual ~Scene();

            virtual void handle_input() = 0;
            virtual void update();
        protected:
            Game *game;
        };
    }
}

#endif
//Game/Scene/Scene.cpp
#include "scene.hpp"

#include <iostream>

Game::Scene::Scene::Scene(Game *game): game(game) 
{
    std::cout << "Game::Scene::Scene::Scene() > game: " << this->game << std::endl;
}

Game::Scene::Scene::~Scene() {}

void Game::Scene::Scene::update()
{
    std::cout << "Game::Scene::Scene::update(): game: " << game << std::endl;
}
//Game/Scene/start.hpp
#ifndef GAME_SCENE_START_H
#define GAME_SCENE_START_H

#include "scene.hpp"

namespace Game
{
    namespace Scene
    {
        class Start:
            public Scene
        {
        public:
            Start(Game *game);
            
            void handle_input() override;
            void update() override;
        protected:
            Game *game;
        };
    }
}

#endif
//Game/Scene/start.cpp
#include "start.hpp"
#include "../game.hpp"

#include <iostream>

Game::Scene::Start::Start(Game *game): Scene(game) {
    std::cout << "Game::Scene::Start::Start() > game: " << this->game << std::endl;
}

void Game::Scene::Start::handle_input()
{}

void Game::Scene::Start::update()
{
    Scene::update();
    std::cout << "Game::Scene::Start::update(): game: " << game << std::endl;
    game->set_keep_going(false);
}
//Game/game.hpp
#ifndef GAME_H
#define GAME_H

#include "Scene/scene.hpp"
namespace Game
{
    class Game
    {
    public:
        Game();
        void loop();

        void set_keep_going(bool state);
        void set_scene(Scene::Scene *scene);
    private:
        bool keep_going;
        Scene::Scene *current_scene;
    };
}

#endif
//Game/game.cpp
#include "game.hpp"

#include <iostream>

Game::Game::Game(): 
    keep_going(true),
    current_scene(nullptr)
{}

void Game::Game::loop()
{
    while(keep_going && current_scene)
    {
        current_scene->handle_input();
        current_scene->update();
    }
    return;
}

void Game::Game::set_keep_going(bool state)
{
    keep_going = state;
}

void Game::Game::set_scene(Scene::Scene *scene)
{
    if(scene)
    {
        if(current_scene)
        {
            delete current_scene;
        }
        current_scene = scene;
    }
}

这是它生成的输出:

Game::Scene::Scene::Scene() > game: 00000210FA38B330
Game::Scene::Start::Start() > game: 0000000000000000
Game::Scene::Scene::update(): game: 00000210FA38B330
Game::Scene::Start::update(): game: 0000000000000000
Segmentation fault

如果我删除我在子类构造函数中用于调试的 'this->' 部分,输出将变成这样

Game::Scene::Scene::Scene() > game: 000001D247B5B370
Game::Scene::Start::Start() > game: 000001D247B5B370
Game::Scene::Scene::update(): game: 000001D247B5B370
Game::Scene::Start::update(): game: 0000000000000000
Segmentation fault

这让我觉得更奇怪的是它突然决定自行重置。

毫无疑问,我忽略了一个非常简单的事情,或者一些我以前从未 运行 接触过的指针恶作剧,但我对这里可能发生的事情感到困惑。

任何关于我的代码的帮助或反馈都将不胜感激。

您有两个成员变量 Scene::gameStart::game。你永远不会设置 Start::game。默认情况下,game 解析为 Scene::game 并且基础 class 的变量被隐藏。打开编译器警告,也许编译器会警告它,在这种特殊情况下不确定。

修复:

Game::Scene::Start::Start(Game *game): Scene(game), game(game)
 {
    std::cout << "Game::Scene::Start::Start() > game: " << this->game << std::endl;
}

或者只删除 Start::game 并使用 Scene 中的成员。这可能是您最初的意思,因此 protected 限定词。

如果您需要反馈 - 不要使用 new,请改用 std::unique_ptr。更好的是,根本不要使用 ptrs 这不是 Java.