2008-12-15 4 views
3

J'ai une classe abstraite définissant une méthode virtuelle pure en C++:Comment allouer de la mémoire à un tableau d'instances en utilisant une classe abstraite?

class Base 
{ 
Base(); 
~Base(); 

virtual bool Test() = 0; 
}; 

J'ai sous-classé cela avec un certain nombre d'autres classes (qui fournissent une mise en œuvre pour le test()), que je désignerai comme A, B, C, etc. Je veux maintenant créer un tableau de l'un de ces types en utilisant cette classe de base:

int main(int argc, char* argv[]) 
{ 
    int size = 0; 
    Base* bases = new Base[10]; 

    bases[size++] = new A(); 
    bases[size++] = new B(); 

    for (int i = 0; i < size; i++) 
    { 
     Base* base = bases[i]; 
     base->Test(); 
    } 
} 

(Excuse toute erreur je aurais pu faire, j'écris ceci à la volée fournir un exemple simple). Le problème est que je ne peux pas instancier le tableau car cela nécessiterait de créer une instance de la classe Base (ce qu'elle ne peut pas faire car elle est abstraite). Cependant, sans cela, il n'a pas alloué la mémoire nécessaire pour assigner aux indices du tableau, et fournit donc une erreur de segmentation lors de la tentative d'accès à cette mémoire. Je suis sous l'impression que ce n'est pas une bonne pratique de mélanger de nouvelles et supprimer avec malloc et gratuit. Il se peut que j'aie confondu la façon dont cela devrait être utilisé et je devrais essayer d'utiliser des modèles ou d'autres mécanismes pour le faire, mais j'espère avoir fourni suffisamment d'informations pour illustrer ce que je tente de faire .

Alors, quelle est la meilleure façon de procéder et comment contourner ce problème d'allocation de mémoire à une classe abstraite?

Merci, Dan

+0

Destructeur devrait également être virtuel –

+1

+1 pour ne pas avoir peur de demander – paxos1977

Répondre

12

Il y a seulement un léger malentendu dans ce code. Au lieu d'allouer des objets de base, vous devez allouer des pointeurs. Un pointeur peut exister à tout moment. Un pointeur vers une classe abstraite, à un type incomplet, et même d'annuler est valable:

int main(int argc, char* argv[]) 
{ 
    int size = 0; 
    Base** bases = new Base*[10]; 

    bases[size++] = new A(); 
    bases[size++] = new B(); 

    for (int i = 0; i < size; i++) 
    { 
     Base* base = bases[i]; 
     base->Test(); 
    } 
} 
+0

Grande réponse. Je lancerais une programmation défensive. Définissez tous les pointeurs sur NULL. memset (bases, NULL, sizeof (Base *) * 10); Juste pour me protéger. Bonne réponse cependant. – baash05

+0

baash05, merci pour la louange :) new Base * [10](); est suffisant pour les annuler tous. J'aime cette fonctionnalité de nouveau. –

+0

Non sauf le coffre-fort. Utilisez boost: ptr_vector plutôt qu'un tableau. –

6

Tout d'abord, assurez-vous que votre destructor est également déclarée comme virtuelle:

virtual ~Base(); 

Vous êtes mieux sur le stockage d'un tableau de pointeurs sur des instances:

Base** bases = new Base *[10]; 
5

Un tableau repose sur l'ensemble de ses éléments ayant la même taille. Lorsque vous avez des classes C++ dérivées de la même base, les instances peuvent avoir n'importe quelle taille. Ainsi, peu importe si la base est abstraite ou non, vous ne pouvez pas allouer un tableau d'instances de base, et ensuite mettre des instances dérivées à cet endroit. Comme d'autres réponses disent, vous devez utiliser des pointeurs. Allouer un tableau de pointeurs à la base, puis allouer diverses instances dérivées et stocker le pointeur dans le tableau.

Questions connexes