3

私は C++ が初めてで、仮想関数の何が問題なのかを理解するのに苦労しています。だから、ここに私が持っているものがあります:

GEntity.h

class GEntity
{
public:
    //...
    virtual void tick(void);
    virtual void render(void);
    //...
};

GEntity.cpp

//...
void GEntity::tick(void){}
void GEntity::render(void){}
//...

GLiving.h

class GLiving : public GEntity
{
public:
    //...
    virtual void tick(void);
    virtual void render(void);
    //...
};

GLiving.cpp

//...
void GEntity::tick(void){}
void GEntity::render(void){}
//...

次に、この 2 つのメソッドの独自のバージョンを実装する GLiving (Player、Enemy) から派生した他のクラスがあります

class Player : public GLiving
{
public:
    //...
    void tick(void);
    void render(void);
    //...
};

Player.cpp

//...
void GEntity::tick(void)
{
    //Here there's some actual code that updates the player
}
void GEntity::render(void)
{
    //Here there's some actual code that renders the player
}
//...

さて、クラス Player のオブジェクトを宣言し、render/tick メソッドを呼び出すとすべてうまくいくのですが、GEntity の arraylist (作成した構造体) に自分のプレーヤーを追加してから、それを取り戻すと、GEntityとして取得し、派生クラスであることを知らずにrender/tickメソッドを呼び出す必要があります...上記のコードで試しましたが、次の行でアクセス違反が発生します抽出された GEntity で render メソッドまたは tick メソッドのいずれかを呼び出します...
...実現したいことはありますか?
(私の英語が下手で申し訳ありませんが、私はイタリア人です)

4

1 に答える 1

3

thenの配列がある場合GEntity、派生型を「追加」するたびに、これと同等のことが起こります。

GEntity g;
Player p;
g = p; // object slicing, you assigned a Player to a GEntity object.
g.render(); // GEntity::render() gets called

一方、基本クラスへのポインターを使用して、派生メソッドにアクセスできます。

GEntity* g;
Player p;
g = &p;
g->render(); // calls Player::render()

したがって、コンテナー内のポリモーフィズムに対処する方法は、基本クラスへの (できればスマートな) ポインターの配列/コンテナーを用意することです。この例では、簡単にするために生のポインターを使用していますが、実際のコードではスマート ポインターを使用する必要があります。

std::vector<CEntity*> entities;
entities.push_back(new Player);
entities.push_back(new GLiving);

// some c++11
for ( auto e : entities) {
  e->render();
}
于 2012-11-22T19:07:53.917 に答える