Vecteurs et polymorphisme en C : le découpage d'objets dévoilé
Lorsque l'on traite des vecteurs de hiérarchies d'héritage en C, on peut rencontrer des subtilités subtiles qui peuvent empêcher le comportement prévu. Prenons l'exemple suivant :
<code class="cpp">class Instruction { public: virtual void execute() { } }; class Add: public Instruction { private: int a; int b; int c; public: Add(int x, int y, int z) {a=x;b=y;c=z;} void execute() { a = b + c; } };</code>
Maintenant, imaginez stocker un objet Add dans un vecteur de pointeurs de classe de base :
<code class="cpp">void some_method() { vector<Instruction*> v; Instruction* i = new Add(1,2,3) v.push_back(i); }</code>
Plus tard, dans une méthode distincte, nous essayons d'invoquer le exécuter la fonction sur le dernier élément du vecteur :
<code class="cpp">void some_other_method() { Instruction ins = v.back(); ins.execute(); }</code>
Une idée fausse courante est que la fonction d'exécution se comportera comme si elle était appelée sur un objet Add. Cependant, ce n'est pas le cas.
Le problème vient de la façon dont les vecteurs stockent les valeurs : ils stockent des copies d'objets, pas des références. Par conséquent, lorsque vous poussez l'objet Add dans le vecteur, il est copié, ce qui entraîne un objet de type Instruction, perdant les données et méthodes spécifiques à Add. C'est ce qu'on appelle le découpage d'objets.
Pour éviter le découpage d'objets, nous devons modifier notre vecteur pour contenir des références au lieu de copies :
<code class="cpp">vector<Instruction*> ins</code>
Alternativement, nous pouvons utiliser std::reference_wrapper :
<code class="cpp">vector< std::reference_wrapper<Instruction> > ins</code>
En utilisant des références, nous conservons le type d'origine de l'objet dans le vecteur, permettant un comportement polymorphe comme prévu.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!