J'essaie de mettre en œuvre une classe virtuelle avec une méthode virtuelle pure et «copier et échanvoir», mais j'ai rencontré des problèmes. Le code ne compile pas car je crée une instance dans l'opérateur d'affectation de la classe A contenant une méthode virtuelle pure.
Y a-t-il une façon d'utiliser la méthode virtuelle pure et de copier et échanger des idioms? P>
In member function âA& A::operator=(const A&)â:| error: cannot declare variable âtmpâ to be of abstract type âAâ| because the following virtual functions are pure within âAâ:| virtual void A::print(std::ostream&)|
4 Réponses :
Lorsque votre compilateur vous informe, vous ne pouvez pas créer une variable de type abstrait. Il n'y a aucun moyen de danser autour de cela.
Ceci vous laisse trois options principales: P>
Premièrement, vous pouvez simplement vous débarrasser des méthodes virtuelles pures et fournir un peu de talon dans chacun d'eux qui appelle std :: terminer code code >
, qui perfectionnerait évidemment la détection de temps de compilation de savoir si toutes les méthodes virtuelles (anciennes) pure sont remplacées dans toutes les classes dérivées. P>
Cela provoquera Tranchement , car il ne copiera que la classe de base et tout ce qui indique que la classe dérivée est perdue. P>
similaires à cela, vous pouvez créer une classe dérivée qui implémente toutes les méthodes virtuelles avec des talons simples (éventuellement appeler std :: ter minate code>
) et est utilisé uniquement comme une "version instantanée de la classe de base". P>
La partie la plus importante à mettre en œuvre pour cette classe serait un constructeur qui prend un Constons référence à la classe de base, de sorte que vous pouvez simplement l'utiliser au lieu de copier la classe de base. Cet exemple ajoute également un constructeur de déplacement, car je suis un fétichiste de la performance. P>
Ceci provoque la même chose Tranchement problème comme première option. Cela peut être votre résultat souhaité, en fonction de ce que vous faites. P> Remarque: il s'agit vraiment d'une variable de type Enfin, vous pouvez ajouter un A code>, bien que j'ai dit Cela ne pouvait pas être fait. La seule chose que vous devez être consciente est que la variable de type
a code> vit dans une variable de type
instantiediatablea code>! P>
Utilisez une copie usine H3>
Copier virtuel A * () = 0; code> à la classe de base. Votre classe dérivée
B code> devra ensuite l'implémenter comme
a * copie () remplacer {retour nouveau b (* this); } code>. La mémoire dynamique de la raison est nécessaire, car vos types dérivés peuvent nécessiter une mémoire plus arbitraire que votre classe de base. P> P>
Le compilateur a raison. La classe in b, vous venez de déclarer le En la mettant en œuvre, il compile une amende (si nous ignorons diverses avertissements): P> A code> est une classe abstraite, vous ne pouvez donc pas créer d'instances de celui-ci dans l'opérateur
= code>.
imprimer code> fonction, mais vous ne l'avez pas impliqué. Signification, vous obtiendrez des erreurs de liaison. P>
void B::print(ostream & os )
{
os << m_att;
}
Vous êtes juste confronté au fait que l'héritage fonctionne maladroitement avec la sémantique de la copie.
Par exemple, imaginez que vous avez trouvé un astuce pour passer la phase de compilation, ce qui signifierait (l'exemple suivant utilise l'affectation, mais le problème est identique à une copie): P>
// class A // a class B : public A // another class C : public A inheriting publicly from A // another class D : public B inheriting publicly from B B b1; C c1; D d1; // Which semantic for following valid construction when copy/assignment is defined in A ? b1 = c1; b1 = d1; A &ra = b1; B b2; // Which semantic for following valid construction when copy/assignment is defined in A ? ra = b2; ra = c1; ra = d1;
Cela ne répond pas vraiment à la question de l'OP.
@ Lethal-guitare: Eh bien, je pense que je le fais. C'est parce que la question, à mon avis, ne peut pas être répondue correctement sans créer un gros problème de conception. Il répond donc à la question en disant que le numéro initial est dans le souhait de mettre en œuvre une copie et un échange pour un type d'entité.
Je vois, bien, vous pourriez envisager de la modifier dans votre réponse pour le rendre plus clair.
CRTP est un choix: classe d'utilisateurs: p> acclamations,
Fm. P> p>
Vous ne pouvez pas avoir
un TMP (rhs); code>.
A code> est une classe abstraite.
@MOHITJAIN Je pense qu'il est bien conscient de cela. C'est pourquoi il demande comment travailler autour de cela.
Peut-être Cette réponse est également utile
L'idiome Copy & Swap ne doit pas être combiné avec des fonctions virtuelles / des hiérarchies de classe. Cela conduit à la tranchée (et à l'UB) et à la mise en œuvre lente (car votre objet de copie temporaire crée une table de fonction virtuelle complète). Au lieu de cela, si vous souhaitez duplication / affectation avec une classe de base virtuelle, base de votre implémentation sur un Fonction clone avec type de retour Covariant .
BTW: Les plus avantages de la copie et de l'échange sont venus si vous faites un & opérateur = (un rhs) {échangez (* this, rhs); retour * ceci; }