Problème Méthode propre à une Classe fille

Fermé
hobro - 7 juin 2008 à 18:43
 lola17 - 7 avril 2009 à 12:06
Bonjour,

En fait, j'ai une classe mère qui à plusieurs classes filles, et certaines classes filles ont leur méthode propre.
Mon problème est que je n'arrive pas à appeler les méthodes propres des classes filles sans devoir les declarer comme virtuelles dans la classe mère et donc de les déclarer aussi dans les autres classes filles, qui n'ont pas besoin de cette méthode. Pour les méthodes communes à toutes les classes filles, et donc dans la classe mère, ça marche très bien, mais pour une méthode qui n'est que dans une seule classe fille, je ne sais pas comment faire. De plus, ces méthodes, je les ai declarées en virtuelle pure dans la classe mère, vu qu'elle n'entre en jeu que dans une des classes filles.

Merci d'avance pour l'aide apportée.

4 réponses

Marco la baraque Messages postés 996 Date d'inscription vendredi 9 mai 2008 Statut Contributeur Dernière intervention 5 novembre 2009 329
7 juin 2008 à 19:33
Bonjour,
C'est du C++ j'imagine.
Première solution : tu utilises une classe abstraite au lieu d'avoir une interface, et dans laquelle tu écris un corps vide pour ta méthode (c'est en gros un peu le même principe que ce que fait le pattern adapter). Comme ça tu n'es pas obligé de réécrire tes autres classes filles.
Mais bon, ce n'est pas top top car tu vas insérer une nouvelle méthode dans ton interface (ou plutôt classe abstraite), et qui est peut-être trop spécifique pour être déclarée ici.

Deuxième solution : Tu écris ta méthode dans ta classe fille, comme tu l'as fait initialement. Tu manipules ton objet à travers ton interface comme tu le faisais initialement, et au moment d'appeler la fameuse méthode, tu castes ton objet dans un objet de classe fille. A mon avis c'est ce qu'il faut faire.

Cordialement
0
Tout d'abord, merci de m'accorder un peu de temps.

Oula, c'est ce que je me suis dit quand j'ai mis mon problème par écrit, que j'allais avoir des réponses par écrit que je risquais de pas trop comprendre, C'est le cas, j'ai un peu de mal. Je vais mettre une partie de mon code pour que tu puisse m'expliquer directement, ça sera plus simple pour moi.

Alors voilà le code que j'ai écris :

class cases
{
protected :
string nom;
int pos;
int prix;
int loyer;
string proprietaire;
public :
cases(string _nom, int _pos, string indice_case);
virtual int get_loyer();
virtual int get_prix();
virtual string get_nom();
virtual get_gaindessus()=0;
};

class cImpot : public cases
{
public :
cImpot() : cases("Impot",5,"Autre") {};
int get_loyer();
int get_prix();
string get_nom();
};

class cDepart : public cases
{
private :
int gain_dessus;
int gain_passage;
public :
cDepart() : cases("Depart",0,"Autre"), gain_dessus(40000), gain_passage(20000) {};
int get_gaindessus();
int get_gainpassage();
int get_loyer();
int get_prix();
string get_nom();
};

int main()
{
cases* table[40];
table[0]=new cDepart;
table[1]=new cImpot;
....
....

cout<<table[0]->get_gaindessus()<<endl;
}

Voilà, et donc quand je compile il me dit que je peux pas et me marque cette erreur :
cannot allocate an object of abstract type «cImpot»
cImpot.h:9: note: because the following virtual functions are pure within «cImpot»:
cases.h:23: note: virtual int cases::get_gaindessus()

Donc que dois je faire ??

Merci encore.
0
Marco la baraque Messages postés 996 Date d'inscription vendredi 9 mai 2008 Statut Contributeur Dernière intervention 5 novembre 2009 329
7 juin 2008 à 22:30
Rebonsoir,
Tout d'abord j'ai fait très peu de C++, et ça fait longtemps.
Cependant, ce que je dois dire sur ton code :
- les méthodes spécifiques à chaque classe ne doivent pas être écrites dans ta classe abstraite "cases"
- virtual te permet de définir les méthodes qui pourront être utilisées par polymorphisme, et le =0 signifie que ta fonction n'a pas d'implémentation. Dans ton cas, tu n'as qu'une méthode qui est =0, donc tu as une classe abstraite et non une interface. Pour avoir une interface, il faut que toutes tes méthodes soit =0 (mais dans ton cas je trouve qu'il faut garder une classe abstraite).

Ici ton compilateur te dit que ta classe "cImpot" est une classe abstraite. En effet, "cImpot" étend ta classe abstraite "cases", qui définit une méthode =0, donc tu est obligé de fournir une implémentation à cette méthode dans ta classe "cImpot", sinon elle est elle-même considérée comme une classe abstraite (certaines méthodes sont implémentées, d'autres non), et elle ne peut pas être instanciée.

Voici un exemple de code pour t'expliquer un peu mieux :
class maClasseAbstraite {
//pas de constructeur car pas instanciable

virtual int methode1();
virtual int methode2(); 
};

class maClasseFille : public maClasseAbstraite {
//les constructeurs
maClasseFille(int att1, string att2);
...

//les méthodes surchargées, ici juste methode2
virtual int methode2(); 

//les méthodes spécifiques à ta classe
int methode3();
};

int main() {
/*comme dans ton code, on manipule les objets filles par le biais des objets (interface ou classe abstraite) dont ils héritent, et grâce au mot clé virtual, les méthodes appelées sont celles de objets contenus, et non pas des objets conteneurs*/
maClasseAbstraite * conteneur = new maClasseFille(1,"toto");

// ensuite essaie ça (je ne sais pas si ça marche mais il faut chercher de ce côté là)
((maClasseFille) conteneur).methode3();
}
0
Re

J'ai bien compris tous ce que tu as dis, et donc agis en conséquence.
La méthode propre de la classe cDepart n'est plus écrite dans la classe cases.
Mais je n'arrive toujours pas à appeler cette fonction "get_gaindessus" de la classe fille cDepart.

Si je déclare dans le main une classe "test" de type cDepart, et que je tape ensuite :
cout<<test.get_gaindessus()<<endl;
et bien ça marche très bien, et c'est logique.

Mais avec ce type de déclaration :
cases* table[40];
table[0]=new cDepart;
table[1]=new cImpot;
...
...

et en tapant ensuite ces lignes, j'ai des erreurs de compilation :
cout<<((cDepart) table[0])->get_gaindessus()<<endl;
ou
cout<<table[0]->get_gaindessus()<<endl;

Pour la premiere j'ai l'erreur :
main.cpp:40: erreur: no matching function for call to «cDepart::cDepart(cases*&)»
cDepart.h:15: note: candidats sont: cDepart::cDepart()
cDepart.h:9: note: cDepart::cDepart(const cDepart&)
Celle la je ne la comprend pas trop.

Et pour la deuxieme :
main.cpp:40: erreur: «class cases» has no member named «get_gaindessus»
N'ai je pas pourtant changé le type de table[0] en cDepart ??
Qu'ai je fait réèllement à la ligne table[0]=new cDepart??

Voilà, en espérant que vous puissiez m'aidez.
Merci d'avance, et surtout merci à Marco la baraque.
0
Marco la baraque Messages postés 996 Date d'inscription vendredi 9 mai 2008 Statut Contributeur Dernière intervention 5 novembre 2009 329
8 juin 2008 à 00:46
Pour la première erreur, c'est une erreur de constructeur. En gros, il te dit que la classe cDepart possède deux constructeurs : le constructeur par défaut et le constructeur par recopie), et que celui que tu essaies d'utiliser n'existe pas. En général, pour corriger ce problème, il faut écrire le constructeur souhaité.
Cependant, dans ton cas, tu as cette erreur car tu écris mal ton instanciation.
Si tu as un constructeur du type: cDepart(), alors pour instancier, tu fais new cDepart();.
Si tu as un constructeur du type cDepart(int a, string b), alors tu fais new cDepart(2,"chaine"); par exemple, et non pas new cDepart;.

Pour la seconde, c'est une erreur bien normale : ta classe cases n'a pas de méthode get_gaindessus si j'ai bien compris, puisque tu ne l'as définie que dans ta classe fille cDepart. Donc lorsque tu essaies d'appeler ta méthode sur ta classe cases, le constructeur te dit qu'il n'y a pas de méthode correspondante.

Qu'ai je fait réèllement à la ligne table[0]=new cDepart??
table est de type cases*, donc c'est un tableau dans lequel tu peux insérer des instances de classe cases et de ses filles.
Sur cette ligne, tu crées une instance de cDepart que tu stockes dans la première cellule de ton tableau.
0
ba oui je comprend tout a fait !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! moi aussi sa m'arrive
0