Un vettore di puntatori a diverse classi derivate della stessa classe base

2

Sto scrivendo un gioco in C ++ che ha diversi tipi di nemici. Ho definito una classe base nemica e ho anche classi derivate enemy1 , enemy2 ecc. Ora per aggiornare questi nemici in ogni iterazione del gioco, voglio avere un array: EnemyArray con i suoi elementi che puntano ai nemici esistenti in modo che possa essere sicuro di aggiornare tutti loro con la loro versione di update () , ecc.

Un modo per farlo sarebbe definire array separati per ogni tipo di nemico e sarebbe un modo pulito per risolvere il problema. Tuttavia, mi stavo chiedendo se il fatto che queste classi nemiche derivino tutte dalla stessa classe base rende possibile in qualche modo avere il mio EnemyArray come una matrice di Enemy e fai alcune modifiche più tardi.

    
posta Maths noob 08.07.2014 - 15:39
fonte

2 risposte

0

È possibile specificare una classe base con funzione virtuale Aggiornamento e classi derivate che sostituiscono questa funzione. Ecco un semplice esempio:

class Enemy
{
public:
    // this is abstract function, but you can also add implementation 
    // as default behavior for derived classes
    virtual void Update() = 0; 
};

class Enemy1 : public Enemy
{
public:
    void Update()
    {
        // update Enemy
    }
}

class Enemy2 : public Enemy
{
    void Update()
    {
        // update Enemy
    }
}

Quindi crea un vettore di puntatori alla classe base e riempi con oggetti di tipo specifico:

vector<Enemy*> enemies;
enemies.push_back(new Enemy1());
enemies.push_back(new Enemy2());

E la tua funzione UpdateAll può assomigliare a questa:

void UpdateAll()
{
    for (int i = 0; i < enemies.size(); ++i)
    {
        enemies[i]->Update();
    }
}

Poiché stai usando i puntatori, non dimenticare di rilasciare tutta la memoria allocata alla fine del gioco.

    
risposta data 08.07.2014 - 16:05
fonte
0

(Sto assumendo C ++)

std::vector conserva i suoi elementi in base al valore, quindi se archivi sottoclassi stai tagliando gli oggetti.

Puoi usare l' idioma PImpl per evitare questo, hai una classe Enemy concreta che contiene un puntatore (unico) ad un nemico concreto un IEnemy astratto che contiene il codice personalizzato.

class Enemy
{
  Point location;
  std::unique_ptr<IEnemy> pimpl;

  public:
    Enemy(IEnemy&& pimpl): pimpl(pimpl), location(){}

    void onTick(World w){
        pimpl->onTick(w);
    }
}

Puoi invece tenere puntatori nel tuo vettore std::vector<std::unique_ptr<Enemy>> in modo che non li trattiene per valore.

    
risposta data 08.07.2014 - 15:52
fonte

Leggi altre domande sui tag