Question

J'ai eu du mal à implémenter des fonctionnalités pour la sérialisation de certaines classes de mon jeu. Je stocke des données dans un fichier texte brut et je veux pouvoir sauvegarder et charger à partir de celui-ci. Les détails de ceci, cependant, ne sont pas pertinents. Le problème est que j'essaie de rendre chaque objet intéressant pour que le fichier de sauvegarde puisse se sérialiser. Pour cela, j'ai défini une interface ISerializable, avec des déclarations purement virtuelles de l'opérateur & Lt; & Lt; et opérateur > >.

La hiérarchie de classe ressemble à ceci

              -> GameObject -> Character -> Player ...
ISerializable               -> Item -> Container ...
              -> Room ...

Cela signifie qu'il existe de nombreuses situations possibles pour la sérialisation des objets des différentes classes. Les conteneurs, par exemple, doivent appeler l'opérateur & Lt; & Lt; sur tous les éléments contenus.

Maintenant, depuis l'opérateur > > est virtuel, je me suis dit que si je voulais sérialiser quelque chose qui implémente la fonctionnalité définie dans ISerializable, je pourrais faire quelque chose comme

ostream & Player::operator<<(ostream & os){
    Character::operator<<(os);
    os << player_specific_property 1 << " " 
       << player_specific_property 2 << "...";
    return os;
}

et ensuite

ostream & Character::operator<<(ostream & os){
    GameObject::operator<<(os);
    os << character_specific_property 1 << " " 
       << character_specific_property 2 << "...";
    return os;
}

mais j’ai vite compris que cette première tentative était illégale. Ce que je demande ici, c’est comment puis-je résoudre ce problème ?

Je n'ai pas envie d'implémenter une fonction manuellement pour chaque classe. Je suppose que je recherche quelque chose comme la super fonctionnalité de Java.

Toute aide est appréciée.

- COMMENTAIRES SUR L'ÉDITION ------------

D'accord, la dernière fois, j'étais pressé lorsque j'ai rédigé la question. Le code est maintenant plus comme il était quand j'ai essayé de le compiler. J'ai corrigé la question et le problème que j'avais n'était pas lié à la question posée. J'ai honte de dire que cela a été causé par une erreur suite à une refactorisation importante du code et par le fait que l'opérateur n'a pas été implémenté dans toutes les classes de base.

Merci beaucoup pour les réponses cependant!

Était-ce utile?

La solution

Le problème ne réside pas dans votre tentative d'appeler une fonction virtuelle de manière non virtuelle. Le problème est cette ligne: os = Character::operator<<(os);. Il s’agit d’une tâche, mais std::ostream n’a pas de operator=.

De toute façon, vous n’avez pas besoin de la cession. Le flux renvoyé est le même que le flux que vous avez transmis. La seule raison pour laquelle il est renvoyé est la possibilité de les chaîner.

La solution consiste donc simplement à modifier le code en

ostream & Player::operator<<(ostream & os){
    Character::operator<<(os);
    os << player_specific_property 1 << " " 
       << player_specific_property 2 << "...";
    return os;
}

Autres conseils

Ce n’est pas la surcharge de l’opérateur < < pour les travaux d'ostream. L'opérateur de gauche est un ostream (vous devez donc le surcharger en tant que fonction libre) et l'opérateur de droite est votre objet (c'est pourquoi le mécanisme virtuel ne fonctionne pas facilement.

Je suppose que vous pourriez essayer:

class Base
{
    //...
    virtual std::ostream& output(std::ostream&) const;
};

std::ostream& operator<< (std::ostream& os, const Base& obj)
{
    return obj.output(os);
}

Maintenant, une classe dérivée peut naturellement appeler la méthode de sortie de son (ses) parent (s):

class Derived: public Base
    //...
    virtual std::ostream& output(std::ostream& os) const
    {
        Base::output(os);
        return os << my_specific_data;
    }
};
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top