
Bonjour, dans la catégorie Astuce de programmation C++ : Comment surcharger les opérateurs >> et <<dans une hiérarchie de classes?
En fait, ce n'est pas possible mais il existe une petite astuce pour obtenir un comportement assez proche.
Imaginons la situation suivante: vous avez un programme qui a un modèle de données qui ressemble agrave; ça:
//une classe abstraite pure
class A {
string* name;
public:
virtual string* getName()=0;
};
class B : public A
{
string* d;
public:
B();
~B();
virtual string* getName();
virtual void getD();
};
class C : public A
{
int e;
public:
C();
~C();
virtual string* getName();
virtual void getE();
};
Comment puis-je utiliser les opérateurs << et >> pour sérialiser mes données tout en s'assurant que toute
nouvelle classe modélisée réimplémentera les opérateurs?
La première chose qui passe par la tête, c'est de se dire facile, je définis mes opérateurs en méthodes
abstraites pures et le tour est joué . Et bien non, hélas en C++, les opérateurs >> et << n'appartientent
pas aux classes. Il sont déclarés en ami . C'est donc implossible d'obliger leurs réimplémentations.
L'astuce consiste à définir les opérateurs << et >> pour la classe abstraite et d'ajouter des méthodes virtuelles pures du genres read(); et write(); . Pour l'illustrer, je vais prendre un exemple: vous avez un programme qui gère un parc de véhicule: avion, voiture etc...
Vous avez une classe abstraite avec une méthode pure qui force à réécrire la fonction de validation du
numéro d'immatriculation.
class Vehicule
{
int nb_passagers;
int poids_capacite;
string* immatriculation;
public:
virtual string* getImmatriculation();
virtual bool immatriculationisValid()=0;
virtual int getnb_passagers();
virtual int getPoids();
}; Vous définissez deux classes qui héritent de Vehicule. (Bien sûr, ma modelisation reste basique, je vous conseigne de mettre plusieurs niveaux de classes abstraites (Vehicule_Moteur, Vehicule_Mecanique etc).
class Avion : public Vehicule
{
int altitude_croisiere;
string* carburant;
public:
virtual bool immatriculationisValid();
virtual int getAltitude();
virtual string* getCarburant();
};
class Voiture : public Vehicule
{
int kilometrage;
string* carburant;
public:
virtual bool immatriculationisValid();
virtual int getAltitude();
virtual string* getCarburant();
}; Nous nous retrouvons dans le cas du dessus donc maintenant nous allons ajouter la déclaration des
surcharges d'opérateurs dans la classe abstraite ainsi que les fonctions abstraites pures pour la sérialisation.
class Vehicule
{
int nb_passagers;
int poids_capacite;
string* immatriculation;
public:
virtual string* getImmatriculation();
virtual bool immatriculationisValid()=0;
virtual int getnb_passagers();
virtual int getPoids();
//fonctions abstraites pures
virtual void read(istream & in)=0;
virtual void write(ostream & out) const =0;
//surcharges opérateurs
friend QDataStream& operator<<(ostream& os,const Vehicule&);
friend QDataStream& operator>>(istream& is,Vehicule&);
}; leur implémentation dans le point cpp: ostream& operator<<(ostream& os,const Vehicule& c)
{
c.write(os);//grace au mécanisme du virtual, il ira chercher la méthode write dans la classe fille;
return os;
}
istream& operator>>(istream& is, Vehicule& c)
{
c.read(is);
return is;
} L'étape suivante est de définir les fonctions read et write dans les classes filles: je ne vais vous donner que l'exemple pour la classe voiture.class Voiture : public Vehicule
{
int kilometrage;
string* carburant;
public:
virtual bool immatriculationisValid();
virtual int getAltitude();
virtual string* getCarburant();
virtual void read(istream & in);
virtual void write(ostream & out) const;
};
void Voiture::read(istream & in)
{
in >> kilometrage ;
in >> nb_passagers;
in >> poids_capacite ;
}
void Voiture::write(ostream & out) const
{
out << kilometrage << nb_passagers;
}