0

如您所料,我遇到了一个我无法回答且只能猜测的问题。

运行时多态性是目标,使用虚拟机制,但我得到的结果好像我在抑制它的同时调用了该方法;就像我调用基类方法一样。

我只能猜测我正在以某种方式这样做,调用来自作为基类的对象,尽管它作为派生类构造的。因此,构造为派生,存储为基础。

我确实将它作为静态基类变量存储在 cpp 中,并与多个外部函数接口以在其他地方访问。(也许,这就是问题所在?)

游戏场景.h:

class GameScene {
public:
    GameScene() { SceneInit(); }
    ~GameScene() { }

    virtual void LevelInit() { } // gcc complains w/o {}
    void SceneInit();

    virtual void UpdateLevel( const float& timeDelta ) { } // gcc complains unless {} added
    void UpdateScene( const float& timeDelta );
};

extern void NewScene( const GameScene& level );
extern void UpdateScene( const float& timeDelta );

class TestLevel : public GameScene {
public:
    TestLevel() { SceneInit(); }
    // implementation here in header
    void LevelInit() override
    {
        // level-specific initialization that is apparent at runtime
    }
    void UpdateLevel( const float& timeDelta ) override
    {
        // level-specific checks and performance
        // but, to test, I simply log "This is the test level"
    }
};

class TutorialLevel : public GameScene {
public:
    TutorialLevel() { SceneInit(); }
    // implementation here in header
    void LevelInit() override
    {
        // level-specific initialization that is apparent at runtime
    }
    void UpdateLevel( const float& timeDelta )
    {
        // level-specific checks and performance
        // debug log "This is the tutorial level"
    }
};

游戏场景.cpp:

#include "GameScene.h"

static GameScene currentScene; // I am now wondering if this pattern is the problem (by explicitly storing this as the base class)

extern void NewScene( const GameScene& level )
{
    currentScene = level;
}
extern void UpdateScene( const float& timeDelta )
{
    currentScene.UpdateScene( timeDelta );
}

GameScene::SceneInit()
{
    // general init
    LevelInit(); // this _properly_ calls the subclass overridden version
    // init completion
}
GameScene::UpdateScene( const float& timeDelta )
{
    // general updating and game handling

    UpdateLevel( timeDelta ); // this was _meant_ to call the overridden version, it does not
}

入口点.cpp:

#include "GameScene.h"

int main()
{
    //NewScene( TestLevel() );
    NewScene( TutorialLevel() );
    float deltaTime;
    while (gameLoop)
    {
        deltaTime = SecondsSinceLastFrame(); // pseudo
        UpdateScene( deltaTime );
    }
}

因此,我遵循了一种与 SceneInit() 一起调用 LevelInit() 的模式,该模式在派生类中被覆盖。如果我在 NewScene() 中使用任一派生类构造函数,我会在运行时获得那些 LevelInit() 结果。我认为将此模式与 UpdateScene() 一起使用是安全的。

我看到的是名为 GameScene::UpdateLevel() 的 UpdateScene(),尽管它在子类中被明显覆盖,就像 LevelInit() 一样。

我的(疯狂的)猜测是,我正在调用 UpdateLevel(),就好像我已经明确地将其转换为 GameScene。:\

也许,这是因为我将 currentScene 存储GameScene?(但是,这不是破坏了多态性的目的吗?)

我遗漏了一些关于存储 currentScene 或调用 UpdateLevel() 的内容。我试过这样打电话:

    GameScene *s = currentScene;
    s->UpdateLevel();

读完之后,作为一个指针,虚拟机制应该是找到该方法的最衍生版本。(可惜...)

我希望我能在这里或其他地方找到一个例子,但我的搜索指出了构造函数/解构函数中的虚拟问题,或者只是不使用“虚拟”关键字等。

4

1 回答 1

0

currentScene 一个GameScene。你已经这样声明了。它永远不会是一个GameScene. AGameScene不是 aTestLevel或 a TutorialLevel;它是一个GameScene. 当您分配一个TestLevelTutorialLevel对象时,currentScene您正在对它进行切片

C++ 中的多态性仅适用于指针和引用。指向 a 的指针或引用可以引用GameScenea or对象,但对象不能a or 。TestLevelTutorialLevelGameSceneTestLevelTutorialLevel

这归结为currentScene需要是指向 aGameScene而不是a 的(智能)指针GameScene。然后它可以指向任何派生自 的类的动态分配对象GameScene。例如:

static std::unique_ptr<GameScene> currentScene;

extern void NewScene( std::unique_ptr<GameScene> level )
{
    currentScene = std::move(level);
}

int main()
{
    NewScene( std::make_unique<TutorialLevel>() );
    // ...
}
于 2020-05-17T03:31:56.897 回答