Petit problème avec un héritage : constructeur incorrect ?

Petit problème avec un héritage : constructeur incorrect ? - C++ - Programmation

Marsh Posté le 13-11-2004 à 10:42:04    

Bonjour,
 
j'ai deux classes prédéfinies qui sont typ_piece et typ_piece_prod qui hérite de la première :
 
typ_piece.h

Code :
  1. #include <iostream>
  2. #include <string>
  3. using namespace std;
  4. class typ_piece
  5. {
  6. protected:
  7. string nom;
  8. int code;
  9. public:
  10. typ_piece(string str=NULL, int c=0);
  11. string a_nom(void)
  12. {
  13.  return nom;
  14. }
  15. int a_code(void)
  16. {
  17.  return code;
  18. }
  19. };


 
Le problème se situe au niveau du constructeur de typ_piece_prod, il génère une génère une erreur que je ne comprend pas :
 

prod warning LNK4075: ' /EDITANDCONTINUE' ignoré à cause de la spécification '/INCREMENTAL:NO'
 
prod error LNK2019: symbole externe non résolu "public: __thiscall typ_piece::typ_piece(char *,int)" (??0typ_piece@@QAE@PADH@Z) référencé dans la fonction "public: __thiscall typ_piece_prod::typ_piece_prod(class typ_piece,int,int,int)" (??0typ_piece_prod@@QAE@Vtyp_piece@@HHH@Z)
 
prod fatal error LNK1120: 1 externes non résolus


 
Voici son code :
 
typ_piece_prod.cpp

Code :
  1. #include "typ_piece_prod.h"
  2. typ_piece_prod::typ_piece_prod(typ_piece t, int b, int u, int r)
  3. {
  4. nb_bruts=b;
  5. nb_usi=u;
  6. nb_rebus=r;
  7. }


 
Je pense que le problème a peut-être un rapport avec le "typ_piece t" mais je n'en suis pas sûr. :/
 
Merci pour votre coup de main. :)


Message édité par Master_Jul le 13-11-2004 à 11:40:25

---------------
En français, on écrit "connexion", pas "connection".
Reply

Marsh Posté le 13-11-2004 à 10:42:04   

Reply

Marsh Posté le 13-11-2004 à 10:47:24    

Le compilo te dit que tu n'as pas écrit le constructeur de type_piece, c'est tout.

Reply

Marsh Posté le 13-11-2004 à 11:13:33    

Ah non, c'était bien ça el muchacho, j'ai simplement fait un petit constructeur :
 

Code :
  1. #include "typ_piece.h"
  2. typ_piece::typ_piece(string str, int c)
  3. {
  4. nom=str;
  5. code=c;
  6. }


 
et ça compile, merci à toi, bonne journée. :jap:


Message édité par Master_Jul le 13-11-2004 à 11:40:45

---------------
En français, on écrit "connexion", pas "connection".
Reply

Marsh Posté le 13-11-2004 à 11:31:34    

En fait, il y a un autre problème.
 
Voici le main :
 

Code :
  1. #include <iostream>
  2. using namespace std;
  3. #include "typ_piece_prod.h"
  4. void main()
  5. {
  6. typ_piece MaPiece("T1",200);
  7. typ_piece_prod typ_1(MaPiece,200,120,2);
  8. cout<<typ_1.a_nom()<<endl<<flush;
  9. // cout<<typ_1.a_code()<<endl<<flush;
  10. // cout<<typ_1.a_nb_rebus()<<endl<<flush;
  11. }


 
J'ai utilisé le debugger pour voir où ça posait problème :
MaPiece est correctement créé.
Lorsque je veux créer typ_1, typ_piece_prod rappelle le constructeur de typ_piece mais il ne retrouve pas les valeurs que j'ai donné à l'objet MaPiece.


---------------
En français, on écrit "connexion", pas "connection".
Reply

Marsh Posté le 13-11-2004 à 11:32:52    

et hop, je veux des std::string
 
 
#include <string>
 
 
string machin;
 
 
vire tous ces char*

Reply

Marsh Posté le 13-11-2004 à 11:42:01    

Voilà, c'est fait.


---------------
En français, on écrit "connexion", pas "connection".
Reply

Marsh Posté le 13-11-2004 à 11:54:00    

Bah maintenant, appelle le constructeur de la classe mère depuis le constructeur de la classe dérivée...

Reply

Marsh Posté le 13-11-2004 à 12:03:24    

Ca le fait déjà tout seul, quand on passe en argument "typ_piece t", il va chercher le constructeur.
 
Le problème c'est que le constructeur de "typ_piece" n'a pas l'air de connaître les valeurs de MaPiece.


---------------
En français, on écrit "connexion", pas "connection".
Reply

Marsh Posté le 13-11-2004 à 18:48:23    

:bounce:


---------------
En français, on écrit "connexion", pas "connection".
Reply

Marsh Posté le 13-11-2004 à 22:12:56    

Ca sert à rien de upper, je t'ai dit ce qui n'allait pas.
 
Si tu ne me crois pas, essaye d'enlever la valeur par défaut du deuxième paramètre (remplace "c=0"  par "c" ), et écoute le cri de ton compilateur.

Reply

Marsh Posté le 13-11-2004 à 22:12:56   

Reply

Marsh Posté le 13-11-2004 à 22:22:33    

Comme dit Lam's.  
Le C++ c'est pas magique, tu lui a donné un argument typ_piece mais tu lui a jamais dit quoi en faire, pourquoi donc irait-il considérer qu'il est censé l'intégrer comme base de ton typ_piece_prod?
Fait l'essai en enlevant (comme le dit Lam's) les valeurs par défaut du constructeur, tu verras que ce sont celles qu'il utilise pour construire typ_1
 
Lam's > faudrait pas qu'il crée un constructeur par recopie, là?


Message édité par masklinn le 13-11-2004 à 22:23:38

---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
Reply

Marsh Posté le 13-11-2004 à 22:25:05    

J'appelle le contructeur de la classe mère depuis le constructeur de la classe dérivée, ce qui donne :
 

Code :
  1. typ_piece_prod::typ_piece_prod(typ_piece t, int b, int u, int r)
  2. {
  3. typ_piece::typ_piece();
  4. nb_bruts=b;
  5. nb_usi=u;
  6. nb_rebus=r;
  7. }


 
:??:
 
Je ne comprend pas trop l'intérêt, tu pourrais m'expliquer le pourquoi du comment stp ?
 
En cours, on a appris à utiliser les paramètres d'un constructeur d'une classe parent mais là je ne vois pas trop comment l'utiliser.
 
Ex :
 

Code :
  1. CLecteur::CLecteur(int NoPort) : CRS232(NoPort)
  2. {
  3. CRS232::Initialiser();
  4. Reset();
  5. }


Message édité par Master_Jul le 13-11-2004 à 22:27:33

---------------
En français, on écrit "connexion", pas "connection".
Reply

Marsh Posté le 13-11-2004 à 22:40:42    

Master_Jul a écrit :

J'appelle le contructeur de la classe mère depuis le constructeur de la classe dérivée, ce qui donne :
 

Code :
  1. typ_piece_prod::typ_piece_prod(typ_piece t, int b, int u, int r)
  2. {
  3. typ_piece::typ_piece();
  4. nb_bruts=b;
  5. nb_usi=u;
  6. nb_rebus=r;
  7. }


 
:??:
 
Je ne comprend pas trop l'intérêt, tu pourrais m'expliquer le pourquoi du comment stp ?[/cpp]


Ptain, j'ai pas le courage ce soir. Je te donnes juste le code que tu devrais avoir:

Code :
  1. typ_piece_prod::typ_piece_prod(typ_piece t, int b, int u, int r)
  2.   : typ_piece(t), nb_bruts(b), nb_usi(u), nb_rebus(r)
  3. {
  4. }


 
Ou beaucoup mieux:

Code :
  1. typ_piece_prod::typ_piece_prod(string str, int c, , int b, int u, int r)
  2.   : typ_piece(str, c), nb_bruts(b), nb_usi(u), nb_rebus(r)
  3. {
  4. }


 
En gros, l'intérêt de faire ça, c'est que la classe dérivée réutilise les choses offertes par la classe de base. Lors de sa construction, elle doit donc également construire la classe de base, car un type_piece_prod EST un typ_piece.

Reply

Marsh Posté le 13-11-2004 à 22:47:08    

Merci Lam's, on m'a appris avec la seconde solution, que je comprend pour "typ_piece(str,c)" mais le problème doit venir du fait que je ne connais pas l'écriture "typ_piece(t)".


Message édité par Master_Jul le 13-11-2004 à 22:47:20

---------------
En français, on écrit "connexion", pas "connection".
Reply

Marsh Posté le 13-11-2004 à 22:48:42    

Lam's a écrit :

Ptain, j'ai pas le courage ce soir. Je te donnes juste le code que tu devrais avoir:

Code :
  1. typ_piece_prod::typ_piece_prod(typ_piece t, int b, int u, int r)
  2.   : typ_piece(t), nb_bruts(b), nb_usi(u), nb_rebus(r)
  3. {
  4. }



Pour celui là il faudrait ptet qu'il crée un constructeur de recopie, parce que là tout de suite je ne pense pas qu'il en ait un :whistle:
 
master_jul > typ_piece(t), c'est construire un objet de type typ_piece à partir d'un objet typ_piece existant, donc créer une copie (constructeur par recopie)
 
si ton type est A, son constructeur pas recopie sera de la forme

Code :
  1. A(A& a)
  2. {
  3.     // Effectuer les allocations
  4.     // et les copies de valeurs
  5. }


Message édité par masklinn le 13-11-2004 à 22:51:15

---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
Reply

Marsh Posté le 13-11-2004 à 22:48:57    

Master_Jul a écrit :

Merci Lam's, on m'a appris avec la seconde solution, que je comprend pour "typ_piece(str,c)" mais le problème doit venir du fait que je ne connais pas l'écriture "typ_piece(t)".


Ca fait appel au constructeur par recopie, donc tu construit l'objet 2 fois, et c'est sérieusement à éviter (je pense pas avoir déjà vu ça dans la nature).
 
Utilise donc la deuxième écriture.

Reply

Marsh Posté le 13-11-2004 à 22:54:02    

Lam's a écrit :

Ca fait appel au constructeur par recopie, donc tu construit l'objet 2 fois, et c'est sérieusement à éviter (je pense pas avoir déjà vu ça dans la nature).
 
Utilise donc la deuxième écriture.


2 fois parce que copie pour argument et copie par constructeur?
(et pourquoi ne pas passer l'argument par référence :cry: )


---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
Reply

Marsh Posté le 13-11-2004 à 23:09:13    

Lam's a écrit :

Ca fait appel au constructeur par recopie, donc tu construit l'objet 2 fois, et c'est sérieusement à éviter (je pense pas avoir déjà vu ça dans la nature).
 
Utilise donc la deuxième écriture.


 
C'est pourtant tiré d'un sujet de BTS, les sujets sont peut-être très cons alors, ça ne m'étonnerait pas. Dans le cas présent, je pense qu'il faudrait utiliser la méthode que tu décris même si tu as l'air de la trouver un peu moyenne car les fichiers d'entête sont fournis (le prototype du constructeur est donc figée), on demande juste d'écrire le constructeur "typ_piece_prod()".


Message édité par Master_Jul le 13-11-2004 à 23:10:08

---------------
En français, on écrit "connexion", pas "connection".
Reply

Marsh Posté le 14-11-2004 à 08:56:14    

Masklinn a écrit :

2 fois parce que copie pour argument et copie par constructeur?
(et pourquoi ne pas passer l'argument par référence :cry: )


Effectivement, il est construit 3 fois:
 - une fois à sa construction par l'utilisateur
 - une fois lors de son passage au constructeur du type dérivé
 - une fois lors de la construction de la classe de base
 

Reply

Marsh Posté le 14-11-2004 à 12:05:20    

Lam's a écrit :

Effectivement, il est construit 3 fois:
 - une fois à sa construction par l'utilisateur
 - une fois lors de son passage au constructeur du type dérivé
 - une fois lors de la construction de la classe de base


Ah oui, mais la construction par l'utilisateur elle est explicite, elle se fait pas a moitié planquée sans qu'on sache qu'elle arrive :whistle:  
 
Jul > on peut pas avoir le prototype exact de typ_piece_prod?


---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
Reply

Marsh Posté le 14-11-2004 à 12:07:46    

typ_piece_prod::typ_piece_prod(typ_piece t, int b, int u, int r)

Reply

Marsh Posté le 14-11-2004 à 12:08:27    

la classe complète


---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
Reply

Marsh Posté le 14-11-2004 à 12:09:18    

Ah, eh bien comme je le précisais, je n'ai que les deux fichiers d'entête précisé dans le premier post.

Reply

Marsh Posté le 14-11-2004 à 12:23:34    

il se passe quoi ici ?

Reply

Marsh Posté le 14-11-2004 à 12:51:56    

Eh bien c'est cette syntaxe qui me dérange(ait) :
 
typ_piece_prod::typ_piece_prod(typ_piece t, int b, int u, int r) : typ_piece(t)
 
En lisant ça, j'ai l'impression que "t" est un argument du constructeur typ_piece mais comme on me l'a expliqué, c'est une copie. Et ca serait la solution à ma question.
 

Reply

Marsh Posté le 14-11-2004 à 13:10:49    

Master_Jul a écrit :

Eh bien c'est cette syntaxe qui me dérange(ait) :
 
typ_piece_prod::typ_piece_prod(typ_piece t, int b, int u, int r) : typ_piece(t)
 
En lisant ça, j'ai l'impression que "t" est un argument du constructeur typ_piece mais comme on me l'a expliqué, c'est une copie. Et ca serait la solution à ma question.


oui, on passe effectivement "t" au constructeur de typ_piece (pour construire la partie typ_piece de l'objet typ_piece_prod à partir de t)
 
Pour l'utiliser, il faut créer un constructeur par recopie


---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
Reply

Marsh Posté le 14-11-2004 à 13:15:35    

là c'est la même chose que du code a xterm ou je sais plus qui : tu utilise de l'héritage là où il n'y en pas besoin. Ou alors tu l'utilise bien.
 
Pour contruire un carré, tu m'a pas t'amuser à construire d'abord un //épipède puis à construire par dessus un carré.
 
là c'est la même chose pour créer un typ_piece_prod, tu dois d'abord créer un typ_piece. À part le nommage, il est clair que typ_piece_prod n'est pas un typ_piece
 
Bref y a quelque chose de pas net dans tout ça, un problème de conception et/ou d'implémentation. Là c'est de l'emballage que tu fais, pas de l'héritage.
 
Tu peux encore chercher alors
 
NB : ça sent la factory tout ça

Reply

Marsh Posté le 14-11-2004 à 13:27:46    

Taz a écrit :

NB : ça sent la factory tout ça


Ca sent surtout le paté et l'exercice moisi préfabriqué, genre faire de l'héritage pour faire de l'héritage [:aloy]  

Citation :

tiré d'un sujet de BTS

:whistle:


Message édité par masklinn le 14-11-2004 à 13:28:11

---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
Reply

Marsh Posté le 14-11-2004 à 13:29:16    

sauf que là c'est pas de l'héritage conceptuellement ...

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed