web-dev-qa-db-fra.com

Un vecteur de pointeurs à différentes classes dérivées de la même classe de base

J'écris un jeu en C++ qui a des types d'ennemis différents. J'ai défini une base ennemi classe et j'ai aussi des cours dérivés ennemi1, Enemy2, etc. Maintenant, pour mettre à jour ces ennemis dans chaque itération du jeu, je veux avoir un tableau: Enemyachray Avec ses éléments pointant vers les ennemis existants afin de pouvoir vous assurer de les mettre à jour tout avec leur propre version de PDATE (), etc.

Une façon de le faire, serait de définir des tableaux séparés pour chaque type ennemi et ce serait un moyen propre de résoudre le problème. Cependant, je me demandais si le fait que ces classes ennemies soient dérivées de la même classe de base permet d'en quelque sorte avoir mon ennemi-carray comme une matrice de ennemi ' s et faire quelques modifications plus tard.

2
Maths noob

Vous pouvez spécifier la classe de base avec la mise à jour de la fonction virtuelle et les classes dérivées remplacent cette fonction. Voici un exemple simple:

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

Créez ensuite un vecteur de pointeurs sur la classe de base et remplissez d'objets de type spécifique:

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

Et votre fonction UpdateAll peut ressembler à ceci:

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

Parce que vous utilisez des pointeurs, n'oubliez pas de libérer toutes les mémoires allouées à la fin du jeu.

0
zacharmarz

(Je suppose que c ++)

std::vector détient ses éléments par valeur, donc si vous stockez des sous-classes, vous découpez les objets.

Vous pouvez utiliser le PIMPL Idiom pour éviter cela, vous avez une classe ennemie concrète qui contient un pointeur (unique) sur un ennemi concret d'une ienemée abstraite qui détient le code personnalisé.

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

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

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

Vous pouvez plutôt détenir des pointeurs dans votre vecteur std::vector<std::unique_ptr<Enemy>> Cela ne les détient pas par valeur.

0
ratchet freak