2

私はC ++を初めて使用します。私はJava/Actionscript3のほうが多く、メモリ関連のものをこれまで扱ったことがないため、この質問はおそらく初心者のようです。

とにかく、私が抱えている問題については: シーンは抽象クラスです (したがって、それから派生して、MainScene などの複数のシーンを持つことができます)。

私が SceneManager に実行させたかったのは、選択したシーン (curSc) へのポインタ/参照を持たせることです。次に、次のようにシーンを設定します: setScene(&someScene)

しかし、私が理解しているように、ポインターを取得するには、次のように初期化する必要もあります。しかし、 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

Scene の具体的な派生クラスが必要です。

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

スマート ポインターを使用する必要があり、メンバー変数をパブリックにしないでください。例:

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 に答える
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 に答える