Problème de polymorphisme dynamique
Bonjour à tous,
Je dois implémenter une interface et la tester. Comme mon problème est difficile à expliquer et à comprendre sous forme de prose, je vous le soumets sous forme d'un code prenant l'exemple d'un garage :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
|
#etc...
// Mon interface
class InterfaceVoiture
{
public :
void InterfaceVoiture();
virtual void accelerer() = 0;
virtual void freiner() = 0;
virtual int getVitesseMax() = 0;
virtual std::string getMarque() = 0;
}
// Mon implémentation
class Voiture : public InterfaceVoiture
{
protected :
int vitesseMax;
std::string marque;
public :
Voiture() :
vitesseMax{130},
marque{"Peugeot"}
virtual void accelerer();
virtual void freiner();
virtual int getVitesseMax();
virtual std::string getMarque();
}
// Une autre classe devant agréger mon implémentation
class Garage
{
protected :
// Ici je suis obligé de fournir l'interface et non l'implémentation :
// Cela permet à garages de contenir des classes de test triviales (des mocks) de voitures
// et cela fait partie du cahier des charges...
std::vector<InterfaceVoiture*> voitures;
...
public :
// Même remarque que ci-dessus
InterfaceVoiture* getVoitureAt(int index){return voitures.at(index);}
...
}
// Ma classe de test de l'implémentation
class TestVoiture
{
protected :
Garage* garage;
// Je dois tester la classe voiture en créant d'abord un garage
Voiture* voitureATester;
public :
void testerVoiture(int index)
{
garage = new Garage();
voitureATester = new VoitureATester();
// Malheureusement à cause des contraintes le getter du garage est une InterfaceVoiture* et non une Voiture*...
voitureATester = dynamic_cast<Voiture*>(garage->getVoitureAt(index));
// Évidemment, une interface ne possède pas d'attribut, donc les getters ci-dessous renvoient une SEH exception,
// i.e. un pointeur non initialisé...
std:: cout << voitureATester->getVitesseMaxVoiture() << std::endl; // 130
std::cout << voitureATester->getMarqueVoiture() << std::endl; // Peugeot
}
} |
Comment obtenir la vitesse maximale de la voiture et sa marque sachant :
- Que l'on doit obtenir ces valeurs en créant une voiture contenue dans un garage créé dans la classe de test
- Que le getter permettant d'obtenir une voiture dans la classe "Garage" doit être une interface ?
Inutile de remarquer certaines horreurs telles que l'initialisation des attributs de la voiture à 130 ou "Peugeot" directement, je l'ai fait pour simplifier.
Merci d'avance pour vos réponses !
Ne jamais oublier les constructeurs de copie !
Médinoc,
Après avoir modifié mon code pour que le garage se remplisse d'une voiture à sa construction, je suis toujours tombé sur la SEH exception et j'ai continué à débugger.
Je m'aperçois alors que voitureATester ne possède pas les mêmes attributs que garage->getVoitureAt(index)... En fait, j'ai oublié de définir un constructeur de copie pour la classe Voiture !!
Je le définis alors, et j'écris :
Code:
voitureATester = new Voiture(dynamic_cast<Voiture*>(garage->getVoitureAt(index)));
Et voilà... Malgré le fait que voitureATester soit une Voiture*, on peut parfaitement retourner une InterfaceVoiture* pour getVoitureAt() dans le cadre des contraintes citées plus haut et le caster en Voiture* sans perdre des données ou attributs, contrairement à ce que je pensais.
La perte d'attributs provenait du fait que le constructeur de copie par défaut n'était pas suffisant, d'où la nécessité de ne jamais oublier le constructeur par copie. Merci Médinoc pour ton aide ! :D