通过将对象显式存储为基类,抑制了虚拟机制? [重复]

问题描述 投票:0回答:1

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

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

那么我只能猜测我是以某种方式进行的,调用的对象是来自于 一个基类,虽然它是作为派生类构造的。所以,构造为派生类,存储为基类。

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

GameScene.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"
    }
};

GameScene.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
}

EntryPoint. cpp:

#include "GameScene.h"

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

所以,我遵循的模式是,SceneInit()调用LevelInit(),而LevelInit()在派生类中被重写。如果我在NewScene()中使用任何一个派生类的构造函数,我就会在运行时得到这些LevelInit()的结果。我想,如果把这种模式用在UpdateScene()上,会很安全。

我看到的是UpdateScene()调用了GameScene::UpdateLevel(),尽管它在子类中显然被重写了,就像LevelInit()一样。

我的(野生)猜测是,我 上午 调用UpdateLevel(),就像我明确地把它投射为GameScene一样。 :\\

也许,这是因为我把currentScene存储在了 作为 游戏场景?(但这样一来,不就违背了有多态性的目的了吗?)

我漏掉了关于存储currentScene或者调用UpdateLevel()的东西。我试过这样调用。

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

在读到作为指针的虚拟机制应该找到方法的最衍生版本之后 但可惜......)。

我希望能在这里或其他地方找到一个例子,但我的搜索指出了构造函数deconstructors中virtual的问题,或者只是没有使用'virtual'关键字,等等。

c++ polymorphism run-time-polymorphism
1个回答
0
投票

currentScene a GameScene. 你已经声明了 它永远不会是什么,但一个 GameScene. A GameScene 不是 TestLevelTutorialLevel;它是一个 GameScene. 当您指定了一个 TestLevelTutorialLevel 反对 currentScene 你是 切片 它。

C++中的多态性只适用于指针和引用。 指针或引用到一个 GameScene 可以 参考TestLevelTutorialLevelGameScene 对象不能 a TestLevelTutorialLevel.

归根结底是... currentScene 需要是一个(智能)指针,指向一个 GameScene 而非 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>() );
    // ...
}
© www.soinside.com 2019 - 2024. All rights reserved.