J'ai essayé de trouver une réponse à cela, mais personne ne semble avoir exactement le même problème que moi.
Je travaille avec plusieurs classes dérivées. L'opérateur d'Ostream << pour chacun de ceux-ci devrait imprimer certaines choses communes à chacune, et certaines choses spécifiques à chacun. Plus tard, j'aimerais tirer davantage de ces classes dérivées, et encore une fois les nouvelles classes dérivées doivent imprimer certaines choses dans les "générations" au-dessus d'elles.
Par exemple: p>
la classe de base .h fichier p> le fichier base.cpp comprend ces lignes: p> puis je dérive: (firseDerive.h) p> fidufeuvre.cpp: p> alors je vouloir dériver: p> second.cpp: p> Je pense que le problème est probablement la déclaration dans le Très début du programme, ou les lignes comme Une autre possibilité est que je ne le redécoupe pas dans le fichier de chaque classe héritée . Devrais-je être, et si oui, quelle syntaxe dois-je utiliser? p> Il m'a été suggéré d'utiliser la méthode base :: opérateur <<< / code>. P>
static_cast CODE>, mais mon professeur (celui qui a écrit la mission et ne nous donnera donc pas trop d'aide avec elle) a déclaré qu'il y a une meilleure façon de le faire. Toute suggestion? P> p>
6 Réponses :
Vous ne pouvez pas implémenter l'opérateur << pour Ostreams en tant que membre de classe - il doit s'agir d'une fonction gratuite (éventuellement d'ami). C'est parce que dans l'expression: La chose sur le côté gauche du << ne sera pas une instance de votre classe, ce qui devrait être si c'était membre Fonction. P> Appeler le parent de l'enfant - faire un statique_cast: p> que je pense est la "meilleure" solution. Sinon, donnez à vos classes un appel de fonction nommé impression () qui prend un système d'OStream comme paramètre et utilisez ceci pour implémenter votre opérateur <<. Cela entraînera beaucoup de code Cleer. P> p>
J'ai donc besoin de le redéfinir comme «Code» Ostream & Opérateur << (Ostream & OS, Constons de base et base) '/ Code' Dans la base.h AMD, puis à nouveau comme «Code» Ostream & Operator << (Ostream & OS, Const de famille & Leçonnier) '/ code', etc.?
Ensuite, comment puis-je appeler l'opérateur de parents de l'enfant?
C'est exactement ce que OP essaie d'éviter. Le static_cast code>.
Bien que la mochette, dans ce cas, la fonction d'opérateur <<<< / code> est là pour être invoquée par l'opérateur de diffusion non membre (qui est correctement spécifié).
Pour appeler une méthode de la classe de base, vous pouvez utiliser: mais Ceci pourrait être fait de la même manière pour l'opérateur < <, juste changer le nom Une autre possibilité est de créer une fonction de membre virtuel: p> en classe dérivée Ceci pourrait appeler la fonction d'impression de base: p> alors il suffit d'avoir opérateur <<< / code> est une fonction libre. La seule possibilité sans static_cast, je peux voir, c'est de définir l'opérateur comme un modèle, puis appelez explicitement la spécialisation comme celle-ci: p>
fonction code> pour
opérateur <<< / code> et ajouter les paramètres requis. p>
Opérateur <<< / Code> uniquement pour la classe code> code> et appellera la méthode d'impression appropriée polymorphicaly. Notez que l'opérateur
<<< / code> est une fonction libre. P>
Ai-je besoin de redéclaré opérateur << dans chaque fichier d'en-tête de classe dérivé également, ou ne le remplaçait que chez l'enfant?
Mis à part Qu'est-ce que @Neil dit, il serait probablement préférable de mettre en œuvre une méthode virtuelle donc Vous n'avez besoin que de mettre en œuvre l'opérateur une fois. Vous pouvez également faire le dostream code>, de sorte que vous n'avez pas besoin de la possibilité de prélèvement:
opérateur <<< / code> non-ami et le
dostream code> public, mais c'est probablement préférence personnelle. P> P>
@Juraj: Eh bien, vous l'avez édité pendant que j'ai écrit la réponse, alors je ne le saurais pas.
Le code d'origine dans la question a déjà une fonction virtuelle dans la classe de base apprécie de dostream, étrangement appelé opérateur <<< / code>.
@Juraj, @Xeo - merci! S'il vous plaît laissez-moi savoir si j'ai bien ce droit - lorsque je veux réellement imprimer une instance de dérivée, la ligne que je veux sera STD :: Cout << dérivée; Et cela appellera à l'opérateur de base, qui appelle à son tour la fonction spécifiée pour chaque classe dérivée et à l'intérieur qu'elle utilise la fonction de base.
@Tony - Que suggérez-vous? Je n'ai pas bien compris votre commentaire à Neil. Je suis vraiment un débutant à cela.
@Biu: Eh bien, ce que Xeo et Martin suggèrent essentiellement la même chose que ce que vous aviez - avec la correction donnée dans ma réponse - sauf qu'ils évitent d'utiliser opérateur <<< / code> en faveur d'une fonction virtuelle bien nommée dans la classe de base. Dans l'ensemble, je pense qu'un identifiant approprié est moins cryptique qu'un opérateur utilisé de manière atypique, de sorte que les réponses de Xeo ou de Martin constituent une amélioration - aucune différence significative entre eux (d'où un +1 pour moi).
Une technique simple pour cela est la suivante:
class Base { int FirstClassNumber; public: virtual void serialize(ostream& os) const { os << FirstClassNumber; } }; // Implement the stream operator for the base class. // All it does is call erialize which is a virtual method that // will call the most derived version. ostream& operator << (ostream& os, const Base &base) { base.serialize(os); return os; } class FirstDerived:public Base { int SecondClassNumber; public: // Override serialize to make it call the base version. // Then output any local data. virtual void serialize(ostream& os) const { Base::serialize(os); os << SecondClassNumber; } };
FRICKEREDED.CPP:
os << "The first number is: "; // finish streaming statement with ";" Base::operator<<(os); // separate statement to call this function... os << "The second number is " << SecondClassNumber; // start streaming again
Merci! Je vais jouer avec votre suggestion et celles de @juraj, @ Xeo et des autres commentateurs et voyez ce qui fonctionne le meilleur pour mon programme. Tous mes vœux:)
Voici une légère modification de la réponse de Loki. Au lieu d'avoir une méthode de sérialisation virtuelle, j'utilise une méthode virtuelle to_string. Je pense que cela peut être réutilisé dans plus de contextes émettant à un ostream, qui pourrait être utile. produit P> Base: 1
FirstDerived: 1 2
«Je pense que le problème est probablement ...» - Quels symptômes observez-vous? Erreur de compilation? Ligne, message? Ou comportement de temps d'exécution indésirable? Si oui, quoi et qu'attendez-vous?