2009-09-18 7 views
8

Shape.hC++ méthode redéfinie pas appelé

namespace Graphics { 
class Shape { 
public: 
    virtual void Render(Point point) {}; 
}; 
} 

Rect.h

namespace Graphics { 

    class Rect : public Shape { 

    public: 

     Rect(float x, float y); 
     Rect(); 

     void setSize(float x, float y); 

     virtual void Render(Point point); 


    private: 

     float sizeX; 
     float sizeY; 

    }; 

} 

struct ShapePointPair { 
    Shape shape; 
    Point location; 
}; 

Utilisé comme ceci:

std::vector<Graphics::ShapePointPair> theShapes = theSurface.getList(); 

for(int i = 0; i < theShapes.size(); i++) { 

    theShapes[i].shape.Render(theShapes[i].location); 

} 

Ce code finit par appeler Forme :: Render et pas Rect :: Render

Je suppose que c'est parce que ça donne une forme au Rect, mais je n'ai aucune idée de comment l'arrêter. J'essaie de laisser chaque forme contrôler comment elle est rendue en surchargeant la méthode Render.

Des idées sur la façon d'y parvenir?

+0

Peut-être que vous voulez nous montrer le code qui crée les éléments vectoriels? –

+1

Le problème et la solution sont presque identiques à cette http://stackoverflow.com/questions/1230006/ question. Comme là, vous avez un vecteur de (struct containting a) classe de base concrète, que vous devez créer en * tranchant * des classes dérivées si vous attendez que Rect :: Render soit appelé. –

Répondre

19

Voici votre problème:

struct ShapePointPair { 
     Shape shape; 
     Point location; 
}; 

Vous stockez un Shape. Vous devriez stocker un Shape *, ou un shared_ptr<Shape> ou quelque chose. Mais pas un Shape; C++ n'est pas Java.

Lorsque vous attribuez un Rect au Shape, seule la partie Shape est en cours de copie (ce qui est l'objet trancher).

+0

auto_ptr perd des données lorsque le ShapePointPair est copié dans le vecteur – Mark

+0

@Mark: notée, ta. – dave4420

+1

Merci. J'avais espéré le faire sans pointeurs puisque les formes n'utilisent pas beaucoup de mémoire donc sont simples à copier sur la pile, mais il semble que ce n'est pas possible. Merci à tous pour les réponses rapides. –

1

Le polymorphisme fonctionnera uniquement à partir d'un pointeur vers une forme, et non à partir d'un objet de forme.

3

Ce problème est appelé découpage - vous perdez la fonctionnalité dérivée lors de la copie vers une base. Pour éviter cette utilisation des pointeurs vers la classe de base, à savoir

std::vector<Graphics::Shape*> s; 
s.push_back(&some_rect); 
+0

Merci. Je n'avais pas entendu parler de trancher avant, je vais garder cela à l'esprit la prochaine fois. –

2

Le problème est que dans votre vecteur vous stockez des copies d'objets de forme, et la copie d'un objet de forme ne copie pas les données ou la fonctionnalité de ses classes dérivées - vous êtes slicing le polymorphisme.

Gérez les objets en utilisant new et delete, et arrangez-vous pour que votre vecteur y stocke des pointeurs.

1

Vous accédez directement à l'objet de forme pour le remplacement pour travailler dont vous avez besoin pour accéder à l'objet via un pointeur ou des références.

Par exemple, lorsque vous assigne la forme dans le ShapePointPair le code « tranche » de l'objet et seulement copier le bit de forme dans le ShapePointPair

Faire cela signifie que vous devez regarder la gestion de la mémoire - donc vous pouvez utiliser un pointeur intelligent dans la structure ShapePointPair { forme smart_pointer; Emplacement du point; };

0

Non, ce n'est pas un casting.

Vous pouvez au lieu de stocker une référence à BaseClass Point:

struct ShapePointPair { 
     Shape shape; 
     Point &location; 
}; 

Cette référence doit être définie au moment de la construction pour struct ShapePointPair.Ajouter un constructeur à ShapePointPair pour ce but . Il doit être passé (nouvellement créé) instances de Rect.

Respectez également les responsabilités de gestion de la mémoire ( destructeurs écrits, etc.).

Questions connexes