9
votes

Classe virtuelle pure et collections (vecteur?)

Je travaille sur une application graphique qui utilise des classes virtuelles assez largement. Il a:

  • Une classe d'images, qui est essentiellement une collection de formes.

  • une classe de formes, purement virtuelle et a quelques classes qui héritent de celle-ci:

    • Cercle
    • Polygone
    • rectangle
    • une forme de figure, qui est une figure graphique (également virtuelle), la forme hérite de celle-ci.

      Essentiellement, mon problème se résume à la mise en œuvre de la classe d'images, qui est essentiellement utilisé pour stocker une collection de formes. J'utilise actuellement un vecteur pour stocker des formes, mais il est évident qu'il s'agissait de la mauvaise décision depuis l'instanciation vectorielle de ces formes, ce qui n'est pas bon car ils sont purement virtuels.

      ci-dessous est ma base de code actuelle (résumé un bit): xxx

      Les messages d'erreur que je reçoivent sont juste un tas de ceux-ci:

      image.cpp: 33: instancié de ici /opt/local/bin/../lib/gcc/sparc-sun-solaris2.10/4.4.1/../../../../include/c++/4.4.1/ext/new_allocator. H: 105: Erreur: impossible d'attribuer un objet de type abstrait 'forme' forme.h: 12: Remarque: parce que le virtuel suivant Les fonctions sont pure dans la "forme": forme.h: 58: Remarque: vide virtuel Forme :: get (std :: istream &) forme.h: 31: Remarque: vide virtuel Forme :: Met (STD :: Ostream &) Const forme.h: 36: Note: Vide virtuel Forme :: Échelle (Const Point &, Double) forme.h: 40: Remarque: vide virtuel Forme :: Traduire (Double, Double) forme.h: 45: Note: Vide virtuel Forme :: Reflechorizontalement (Double) forme.h: 49: Remarque: vide virtuel Forme :: réfléchissante (double) forme.h: 52: Remarque: virtuel Shape RectangularArea :: Boundingbox () const forme.h: 21: Remarque: virtuel Forme * forme :: clone () const forme.h: 55: Remarque: vide virtuel Forme :: Dessin (graphiques &) const

      Alors, quel est le moyen idéal de stocker ces formes. Quel type de collection devrais-je utiliser pour stocker ces choses?

      merci


0 commentaires

3 Réponses :


20
votes

Lorsque vous avez besoin de polymorphisme, vous devez utiliser des pointeurs ou des références. Puisque les conteneurs (ou les tableaux) ne peuvent pas stocker des références, vous devez utiliser des pointeurs.

modifier essentiellement le vecteur de votre classe d'image sur: xxx

et modifier correctement l'autre membre Fonctions.

La raison pour laquelle vous ne pouvez pas / ne pas les stocker comme des types de valeur est parce que le vecteur est un conteneur homogène, c'est-à-dire qu'il stocke uniquement les données d'un type (et seulement Un type - les sous-classes ne sont pas autorisées!). La raison en est que le vecteur stocke ses données dans une matrice, qui doit connaître la taille des objets qu'il stocke. Si les tailles de ces objets sont différentes (elles pourraient être pour différentes formes), il ne peut pas les stocker dans un tableau.

Si vous les stockez comme des pointeurs, ils ont tous la même taille ( Tailleof (forme *) ) et ont également accès à la table de la forme, ce qui permet un comportement polymorphe.


2 commentaires

Avec les fonctionnalités C ++ 0X telles que les pointeurs intelligents améliorés et déplacez la sémantique, on pourrait même créer une version de sécurité-sécurité de cette ( vecteur > ).


Si vous n'utilisez pas les pointeurs intelligents, rappelez-vous que le conteneur ne nettoie pas automatiquement les données pointues. Il appelle les destructeurs sur les pointeurs - mais ces destructeurs ne font rien. Vous devriez ajouter un destructeur à votre classe d'images qui iTère à travers les formes les supprimant. En utilisant une classe de pointeur intelligente, comme le suggère BobbymCr, évite ce problème.



4
votes

Utilisez des types de retour covariant. Voir FAQ 20.8 pour votre clone méthodes. Vous pouvez également compter sur la méthode d'usine également pour créer les objets de forme .

En outre, vous ne pouvez pas avoir de conteneur d'objets de classe abstraite, les classes abstraites ne peuvent pas être instanciées. Au lieu de cela, créez un conteneur de pointeurs / références à des objets en béton dérivés. Remarque, si vous utilisez un pointeur, il devient de votre responsabilité de les effacer. Le conteneur ne désactivera pas correctement la mémoire. Vous pouvez utiliser des pointeurs intelligents au lieu des pointeurs bruts pour le gérer plus efficacement. RECHERCHEZ SCOPED_PTR ET SHARED_PTR de BOOST.


1 commentaires

En premier écrémé, j'ai vu les "types de retour de covariant" et supposé que cela répondait à la mauvaise question. Après que la réponse principale ait peut-être gagné, vous avez gagné plus de upvotes. Vous avez mon +1 maintenant.



1
votes

Comme déjà décrit dans un autre polymorphisme de réponse nécessite des références ou des pointeurs. Au lieu de l'allocation de mémoire brute, vous pouvez utiliser des pointeurs intelligents. Vous pouvez créer un conteneur avec xxx

et ajouter des éléments avec xxx

la mémoire est libérée lorsque le vecteur est détruit.


2 commentaires

Serait-ce emplace_back ou push_back ? Si les deux sont valides, push_back peut avoir plus de sens, car emplace_back suggère que vous passez un unique_ptr comme argument sur le < Code> unique_ptr constructeur.


@Nathanpierson Vous avez probablement raison. Les deux sont possibles pour que je vais le changer.