2

我是 C++ 新手,这个问题可能看起来很无聊,因为我只是一个 Java/Actionscript3,而且我以前从未处理过与内存相关的事情。

无论如何,至于我遇到的问题:场景是一个抽象类(所以我可以从中派生并拥有多个场景,例如 MainScene 等)

我想要 SceneManager 做的是有一个指向所选场景(curSc)的指针/引用然后我会像这样设置场景: setScene(&someScene)

但据我所知,要拥有一个指针,我还必须像这样初始化它: curSc = new Scene; 但它不会让我这样做,因为 Scene 是一个抽象类..

class Scene {

public:
    Scene(void){}
    virtual ~Scene(void){}
    virtual void update() = 0;
    virtual void render() = 0;
};


class SceneManager {

public:
    SceneManager(void);
    ~SceneManager(void);
    void setScene(Scene *sc);
    Scene* curSc;
}

到目前为止,在我看来,在这种情况下使用指针是错误的,它不会起作用..但我很想知道如何实现我试图在这里获得的功能

非常感谢你

按要求编辑: 这就是我尝试使用它的方式:

首先,我有一个名为 GameScene 的派生类,它是:

class GameScene : public Scene 
{
public:
    GameScene(void);
    void render();
    void update();
}

在我的 main() 函数中,我有:

GameScene gamescene;
ScreenManager manager;

manager.setScene(&gamescene);
4

4 回答 4

1

你需要一个具体的场景派生类:

class MyScene: public Scene {

public:
   MyScene(void){}
   virtual ~MyScene(void){}
   virtual void update();
   virtual void render();
};

并且 void setScene(Scene *sc) 将是:

void setScene(Scene *sc)
{
  curSc = (Scene*)sc;
}

在这种情况下,sc 将是 MyScene 指针。抽象类实例(即接口)不能被创建,Scene在这里只是一个接口。

于 2013-03-31T15:59:09.350 回答
0

确切地。你不能做

curSc = new Scene  

因为它是抽象的。如果你真的想声明一个实例,Scene那么让它成为非抽象的。即实现所有方法。

或者(我认为这是您打算做的)创建一个继承Scene并实现所有虚拟方法的类。

class View : public Scene {

public:
   View(){}
   virtual ~View(void){}
   virtual void update();
   virtual void render();
};

并实现虚拟方法,如

void View::update() {
//
}

void View::render() {
//
}

然后您可以将 setScene 实现为

void SceneManager::setScene(Scene *sc)
{
  curSc = sc;
}

并称它为

SceneManager smag;
Scene *nsc = new View;
smag.setScene(nsc);
于 2013-03-31T16:10:19.790 回答
0

在这里使用指针并没有错。但与引用不同的是,指针敦促其用户考虑NULL. 这就是警告。参考也可以参考NULL,但增加对它的防御会导致你走向“黑暗面”。因此,假设引用将引用活动对象是合理的,从这个意义上说,引用比指针更好。

现在,如果您真的-真的想保留引用,您可以使用就地构造技术,因为您可以通过构造函数(重新)分配引用:

class SceneManager {

public:
    SceneManager(Scene& sc) : curSc(sc) {}
    ~SceneManager(void);
    SceneManager& setScene(Scene &sc) {
        SceneManager* cheatCompiler = new(this) SceneManager(sc);
        return *cheatCompiler;
    }
    Scene& curSc; 
}

请注意,这是一种古怪的东西。由于编译器总是试图超越我们,我不能保证它在所有情况下都能正常工作。

也就是说,我仍然建议您使用指针。如果你不想一直检查 NULL,你可以实现类似Null Object Pattern的东西。

于 2013-03-31T16:14:42.623 回答
0

您应该使用智能指针,并且不要公开成员变量。例子:

class Scene {
public:
    virtual ~Scene(){}
    virtual void update() = 0;
    virtual void render() = 0;
};

class MyScene : public Scene {
public:
    virtual void update () { /*...*/ }
    virtual void render () { /*...*/ }
};

class SceneManager {

public:
    SceneManager();
    ~SceneManager();
    void setScene(const std::shared_ptr<Scene> & sc) {
       curSc = sc;
    }
private:
    std::shared_ptr<Scene> curSc;
};

void someProc () {
    std::shared_ptr<Scene> sc = std::make_shared<MyScene> ();  
    auto manager = std::make_shared<SceneManager> ();
    manager->setScene (sc);
    // ...
}

如果没有智能指针,这看起来像(但如果不再需要它们,请记住delete创建的对象):new

class Scene {
public:
    virtual ~Scene(){}
    virtual void update() = 0;
    virtual void render() = 0;
};

class MyScene : public Scene {
public:
    virtual void update () { /*...*/ }
    virtual void render () { /*...*/ }
};

class SceneManager {

public:
    SceneManager();
    ~SceneManager();
    void setScene(Scene * sc) {
       curSc = sc;
    }
private:
    Scene * curSc;
};

void someProc () {
    Scene * sc = new MyScene;
    SceneManager * manager = new SceneManager;
    manager->setScene (sc);
    // ...
}
于 2013-03-31T16:25:22.137 回答