Constructeur de copie, agrégation et surcharge de "=" - C++ - Programmation
Marsh Posté le 18-04-2005 à 10:56:44
je dirais que l'interface Smagic doit avoir une méthode clone(); ou mieux si tu veux partager les instances de Smagic, utilise des boost::shared_ptr.
NB: a priori ta classe de base Path est mal nommée, et tu devrais faire de l'héritage privé (car un magicien n'est pas un path, imnsho )
Marsh Posté le 18-04-2005 à 12:30:44
Si tu ne définie pas explicitement l'opérateur =, le compilo copie tout les champs à l'identique (les pointeurs sont copié tel quel, c'est à dire que les pointeurs pointent vers la meme case mémoire).
Je sais pas si c'était celà que tu attendais (comme réponse).
Marsh Posté le 18-04-2005 à 13:03:35
kaktusBigOne a écrit : Bonjour, |
Ben au vu de ççà je sais pas, c'est pour çà
Marsh Posté le 18-04-2005 à 13:23:57
# virtual int GetCriticalhit() { return 0; }
c'est pas ça pour virtual pure. =0
# delete magic1,magic2,magic3;
tu crois faire quoi là ?
Marsh Posté le 18-04-2005 à 13:31:33
Taz a écrit : |
il reserve une séance de plombier
Marsh Posté le 18-04-2005 à 16:54:40
schnapsman : si justement, magician est un type de voie (Path). Path comporte en fait tout attribut partagé par n'importe quel personnage à savoir une force, un niveau etc ... et des méthodes style attack() etc ...
Comme tu t'en doutes, il y a aussi un type fight ...(entre autres). D'ailleus j'ai exactement le mm problème.
Taz : oui je sais pour virtuel pure que c'est le =0. Seulement le virtual int GetCriticalhit()=0 se trouve dans Path et je suis obligé de la redéclarer dans la classe fille Magician si je veux qu'elle soit instantiable. Mm si c'est ballot de se retrouver avec des return 0 mais si je veux profiter d ela ligature dynamique, pas le choix au vu de mes connaissances en C++ (.
Le virtual me sert ici à lancer la méthode correcte (car bien sûr, il y a des classes filles de Magician).
Bien vu pour le delete magic1 etc... Je me pose la mm question de savoir comment être sûr que j'ai bien supprimé mes pointeurs. que je le mette ou non, ça change rien j'ai l'impression.
En fait la question c'est ça (reformulé ..) : Comment supprimer gérer correctement des objets agrégés type pointeur dans une classe à savoir copie et suppression.
Pour un type int* ou float* je sais le faire, pas pour un type classe* ... .
Sympa de répondre si vite en tt cas .
Marsh Posté le 18-04-2005 à 16:55:53
super, t'as rien compris à virtual pure ... çà fait plaisir ...
Marsh Posté le 18-04-2005 à 19:11:50
Taz : je crois surtout que tu devrais mieux lire les posts ...
virtual pure je connais très bien, d'autant que je viens de Java et que la notion d'interface n'existe pas en C++ (eh oui, donc n'utilise pas "interface" pour le C++ stp -je peux pinailler aussi- ...)
Une interface n'est qu'une classe avec que des fonctions-membres virtuelles pure, c'est tout, en C++.
Si tu veux savoir, déclarer une classe en interface te permet :
- d'accélerer le polymorphisme (et dieu que c lent java ..)
- de permettre de proposer une interface commune à tous les descendants (comme faire une classe "pièce" dont descendrait un roi, une reine etc.. ).
le virtual int GetCriticalhit() { return 0; } n'est PAS une fonction-membre virtuelle pure (j'ai jamais dit ça) , seulement virtuelle.
Sinon, explique-moi pourquoi j'aurai parlé de gestion d'objets agrégés, qui est ma question principale depuis le début.
Si j'ai un problème c'est niveau pointeur (là c'est sûr, je suis pas un as).
pour le boost :: shared_ptr : ça ne marche pas avec les conteneur multi_associatifs et malheureusement j'ai un multimap pour gérer mes sorts disponibles.
A moins d'utiliser un de leur conteneur fourni, je vais creuser par là, merci ).
Je ne sais pas si ça marche avec une map seule d'ailleurs,
Lord : oui ok, bien expliqué mais ça ne résoud pas mon souci. Si j'avais int* magic1 à la place de SMagic *magic1, je n'aurai pas eu de soucis.
shnapsman : méthode clone(), il y a un truc comme en Java clone() ??? Ca m'intéresse. Effectivement c'est là aussi que je sens le gros memory_leak se pointer même si c'est pas apparent encore.
Merci pour votre aide, bonne soirée
Marsh Posté le 18-04-2005 à 19:18:20
bon je me casse, j'en ai marre qu'on me fasse le leçon avec autant de balivernes
Marsh Posté le 18-04-2005 à 19:33:34
kaktusBigOne a écrit : Taz : je crois surtout que tu devrais mieux lire les posts ... [...] |
moi je crois que tu devrais être sur de ton coup avant d'essayer de contredire Taz sur le C++...
Marsh Posté le 18-04-2005 à 21:31:59
Harkonnen : Ca ne me dérange pas qu'on dise que mon programme est nul, mais celui qui le dit doit dire pourquoi, c'est la moindre des choses. Et pas me sortir ça :
Assez énorme la réaction de Taz :
j'ai dit :
- Le destructeur est-il correct? Je n'ai aucun plantage mm si mon mago n'a que magic1 d'initailisé par exemple.
Réponse :
- # virtual int GetCriticalhit() { return 0; }
c'est pas ça pour virtual pure. =0
Et alors?? T'as réfléchi deux secondes avant de sortir une truc pareil ?? Heureusement qu'elle est pas virtuelle pure ma fonction, je fais comment pour créer mon mago sinon ??
Excuse ma réaction mais c'est compréhensible là ...
Si c'est une blague, ça me fait pas rire. Bref.
Je doute pas des connaissances de Taz (y'a de jolis codes made by Taz ici) mais il a de ses réponses parfois ... déroutantes.
En attendant, vous m'avez donné quelques pistes ( clone()?? / smart pointer de boost ) et c déjà pas mal en un jour.
Merci encore
Marsh Posté le 18-04-2005 à 21:39:05
delete a, b, c;
et ça c'est pas déroutant ? ...
alors ton blabla, tu le ranges un peu pour le moment, si t'écris ça, c'est que cette aprèm t'as fais ton premier new.
quand a ton foutoir de virtuel pure pas pure : t'as rien compris. le but de virtuelle pure, c'est de forcer la définition par les sous-classes. Si tu définis en filant un comportement bidon par défaut 'pour pouvoir instancier' ... c'est que tu es vraiment perdu ...
EN CLAIR : surcharger une virtuelle pure dans le seul but de pouvoir instancier == INCOMPRÉHENSION TOTALE DU POLYMORPHISME ET DE LA SPÉCIALISATION ET DES CLASSES ABSTRAITES ET DE TOUT, MEME JAVA.
Marsh Posté le 18-04-2005 à 21:44:18
moi aussi des fois je m'ennuie, alors j'écris du code qui sert
1, std::cout << "Hello World !\n", 3;
bjarne a vraiment rien compris.
Marsh Posté le 18-04-2005 à 21:58:46
Bon on va commencer par plier le coup du destructeur
L'op virgule est le moins prioritaire de tous en c++, donc seul le premier pointeur est deleté, les autres à la suite ne génère même pas de code sur un bon compilo (à part un warning monkey proof et encore c'est pas sur). Par contre ça fait un bel exemple de fuite mémoire (un magnifique cas d'école en fait ).
Pas de problème avec ça non plus:
std::multi_map<KeyT, boost::shared_ptr<ElemT*>> |
tu peux en effet avoir n shared_ptr pointant sur le même objet, mais encore une fois ce n'est pas un problème (attention aux cycles tout de même...)
Il n'y a rien de prévu en c++ pour la méthode clone(). Ceci dit tu peux l'imposer par une "interface" Clonable comme en java si tu veux (mais dans ton cas autant shared_ptrer à donf).
Marsh Posté le 18-04-2005 à 23:13:49
Taz : là je vois mieux ce que tu veux dire.
Pour le delete a,b,c .. C'est déroutant pour moi aussi. Non seulement c'est accepté à la compil (Dev C++ est pas commode pourtant ) mais ça plante pas.
J'ai mis ca car c'est ce kom ça que j'ai appris quand on a une classe genre :
class tableau
{
protected :
double *ad;
int n;
public :
tableau(int n) // Construc
{ ad=new double[this->n=n]; }
tableau(const tableau&v) // Construct Copy
{
ad=new double[n=v.v]; // Tableau vide
for (i=0;i<n;i++) { ad[i]=v.ad[i]; }
} // Hop, rempli
~tableau() // Destruct
{ delete ad; }
};
Alors tu vois pourquoi j'ai mis delete magic1,magic2,magic3 dans le destructeur. A tort??
Et le problème -en cas de constructeur de copie obligatoire- est que dans l'exemple le new double(), ça marche mais moi, mon new SMagic() ne marche pas car SMagic est abstraite. Alors s'il faut trouver le type de SMagic, bonjour le dynamic_cast à gogo (((
J'ai aussi lu que si l'un des membres d'une classe est un objet alors c'est son propre constructeur de recopie qui est appelé en cas de recopie.
Si c'est ce qui se passe, bon ok, mais c'est un pointeur .. (pas un Classe objet mais un Classe* objet), ça change quelque chose ou pas dans ce cas???.
Pour ce qui est des fonctions virtuelles de mon programme (ouais enfin essai ), je vais tâcher de développer un peu(c long alors zappe si tu ne veux pas lire).
C'est vrai que c'est difficile de voir pourquoi il y a des virtual partout.
virtual int GetCriticalhit()=0 est écrit tel que dans la classe Path qui est donc abstraite.
Path est ma super-classe, de laquelle dérive obligatoirement tout joueur.
Path possède les attributs communs à tous comme la force, le nombre de point de vies, un répertoire de sorts (vide par défaut) etc ...
et aussi des méthodes non virtuelles comme Attack(Path *player), RangedAttack(Path *player)
également les fonctions virtuelles pures qui sont redéfinies
dans les classes filles instantiables.
2 classes héritent de Path,à savoir Magician et Fight. Ces dernières sont instanciables (correspondent en fait au début du jeu, la voie des armes ou voie magique).
Magician possède trois objets pointant sur SMagic. On peut avoir 3magies différentes donc.
Smagic est une classe abstraite regroupant (un peu comme j'ai fait avec Path) tous les attributs/ méthodes communs de toute magie). En héritent SMagiclife, SMagicdeath etc .. (y'en a 5)
Fight possède un objet pointant sur SFight. Là encore, classe abstraite, regroupant les attributs / méthodes communs de toute sorte de combattant. En héritent SFighter,Sh2hFighter,SArchery.
Si tu choisis un mago, dans la conception du jeu, tu ne fais pas de coup critique, d'où le
virtual int GetCriticalhit() { return 0; }
Si tu choisis un combattant, en revanche, la définition de virtual int GetCriticalhit() change (on renvoie une valeur basée sur ses stats/ dégat initiaux et un jet d'un dé à 100 faces).
On peut choisir un perso hybride, mago + combat ,celle classe fille hérite de Magician, et là, le virtual int GetCriticalhit() change aussi.
Physiquement, on est plus magicien que guerrier.
Il y a aussi une classe hybride combat + mago, qui dérive de la classe combat.
Physiquement, on est plus guerrier que magicien ici. Modification aussi du virtual int GetCriticalhit() en conséquence.
C'est identique avec les GetDefense1() etc...
Comme tu le vois, elles existent vraiment et ont un vrai rôle.
Si je reçois par exemple la valeur zéro en retour de GetDefense1(), ça veut dire que le joueur ne dispose pas de la défense type 1 -ou plutot a une défense type 1 égale à zéro-
Pourquoi je n'ai pas tout simplement défini les GetDefense()() que dans les categories combattantes?
Et bien, les joueurs sont instanciés comme ceci :
SMagic *magiclife = new SMagiclife(levelmagiclife,...,linktogodspell)
SMagic *magicdeath = new SMagicdeath(levelmagiclife,...,linktogodspell)
SFight *fighter = new SFighter (offense,defense...,parry)
Path *player1 = new Magician(force,dext .... ,magiclife,magicdeath)
Path *player2 = new HybridMagician(force,dext...,magiclife,figter)
delete player1;
delete player2; etc ...
Voilà comment s'est goupillé.
Marsh Posté le 18-04-2005 à 23:18:19
dis nous que tu n'as pas lu le dernier message de schnapsmann
Marsh Posté le 18-04-2005 à 23:26:13
schnapsmann :
L'op virgule est le moins prioritaire de tous en c++, donc seul le premier pointeur est deleté, les autres à la suite ne génère même pas de code sur un bon compilo (à part un warning monkey proof et encore c'est pas sur). Par contre ça fait un bel exemple de fuite mémoire (un magnifique cas d'école en fait ).
Merci beaucoup ).
J'ai jamais compris pourquoi Stroustrup disait qu'il avait laissé les déclarations type int a,b,c uniquement à cause du C. Maintenant Ok (Je trouvais ça chouette moi pourtant lol)
Donc acte.
Il faut donc bien que je delete mes objets dans le destructeur mais correctement.
Marsh Posté le 18-04-2005 à 23:26:24
accepté ? moi ça fait 3 lignes de warnings !
le reste je lis pas, t'es pas écrivain, pour un problème aussi simple si t'as besoin d'écrire une tartine, c'est que y a un truc pas clair.
Marsh Posté le 18-04-2005 à 23:34:49
Push : Exact Maintenant c'est intégré ...
Bonne soirée à tous.
Marsh Posté le 18-04-2005 à 23:38:54
ah oui faut fait : ta classe tableau est un massacre
longue vie au segfault
Marsh Posté le 18-04-2005 à 23:58:27
Taz : C'est juste pour te montrer que je n'ai pas mis des virtual pour rien, ils ont vraiment un sens.
Sur que si j'ai que deux classes, je ferai differemment .
Sur dev C++ pas UN warning au fait. Pourtt j'ai pris ce compilo car il est connu pour être assez intraitable et bien
Avec java où tout a un virtual intégré, je trouve très intéressant d'essayer d'en enlever un maximum et c'est pas toujours facile.
schnapsmann : Ok je suivrai ton conseil .. quand je connaitrai bien les pointeurs .
Bonne nuit à tous et merci pour vos précieuses aides.
Marsh Posté le 19-04-2005 à 00:04:09
Taz : oui juste cas d'école qu'on apprend en cours pour débuter en constructeur de recopie. J'y suis passé avec cet exemple pratiquement.
Le coup de la "," ben tu vois, appris nulle part ...
Je préfère un vector <double> et pas de classe à se taper.
Bonne nuit toi aussi (râleur va).
Marsh Posté le 19-04-2005 à 00:13:27
Taz a écrit : ta classe tableau est quand même mitée. |
ouais, enfin il faut bien apprendre aux jeunes à faire
delete [] |
pour libérer un tableau, parce que visiblement ils ne le savent pas!
Marsh Posté le 19-04-2005 à 00:18:44
il a aussi oublié la surcharge de operator= dans sa classe tableau
Marsh Posté le 19-04-2005 à 00:22:24
bah, c'est de bonne guerre. Après comment on fait pour pratiquer le newbie bashing sans eux?
Marsh Posté le 18-04-2005 à 10:37:18
Bonjour,
Merci de m'avoir accepté dans ce forum (déjà ).
Je suis un petit nouveau en C++ (enfin bon je m'en sors un peu quand mm ).
Voilà une question que je pose (et pas trouvé de réponses, curieusement ... )
Quand on fait une agrégation -c'est à dire qu'on utilise un objet implémenté dans un autre- je voudrais savoir comment ça se passe niveau constructeur de copie et surcharge "=" si besoin..
Voici un copier/ coller de la classe "gênante".
- Actuellement, le programme semble marcher (j'arrive en fait à jeter n'importe quel sort et choisir le perso que je veux et simuler des combats joueur vs joueur) sans plantage évident.
- Bon j'ai mis des blabla pour éviter les formules inutiles .
- "Path" est une classe virtuelle comportant données-membres et fonctions-membres communes à toutes les classes.
- Constructeur de copie : C'est bien un des problèmes .. SMagic est virtuel, je ne vois comment faire un new SMagic() ...
- Surcharge de l'opérateur "=". Mm problème que pour le constructeur, surtout que je vais en avoir besoin notamment pour réinitialiser mon mago.
- SMagic ne comporte AUCUNE donnée-membre type pointeur.
Voici donc mes questions sur cette classe :
- Le destructeur est-il correct? Je n'ai aucun plantage mm si mon mago n'a que magic1 d'initailisé par exemple.
- Quand j'utilise une instance de SMagic, dois-je donc faire un constructeur de copie (comme s'il s'agissait d'un int* par exemple) ou alors est-ce la classe SMagic qui doit s'en charger? (dans ce cas, rien car pas de pointeur).
Si oui comment faire? Parce que pour connaitre le type exact de magic1,magic2,magic3 c'est plutôt la galère et bon, dynamic_cast, moins j'en vois mieux je me porte.
- Operateur "=". Idem...
Merci d'avance .