J'ai un petit problème, je veux créer un "operator=" de ma classe Personnage, j'ai cherché et j'ai vu que il fallait le déclarer dans le .h mais il sort quand même une erreur, voici mon Personnage.cpp et mon Personnage.h :
Personnage.cpp :
#include "Personnage.h"
#include <iostream>
//Constructeur
//Bla-Bla-Bla
//Operateur
Personnage& Personnage::operator=(Personnage const& personnageACopier) //Quand on fait david = gontran
{
if (this != &personnageACopier) //On verifie qu'on fait pas gontran = gontran
{
m_vie = personnageACopier.m_vie;
m_mana = personnageACopier.m_mana;
delete m_arme; //On supprime le lien entre le nouveau personnage et l'adresse de l'arme du gars qu'on copiess
m_arme = new Arme(*(personnageACopier.m_arme));
}
return *this;
}
Personnage.h :
#ifndef DEF_PERSONNAGE
#define DEF_PERSONNAGE
#include <iostream>
#include <string>
#include "Arme.cpp"
class Personnage
{
public:
Personnage();
Personnage(string nomArme, int degatsArme);
Personnage(Personnage const& personnageACopier);
void recevoirDegats(int degats);
void coupDePoing(Personnage &cible) const;
~Personnage();
private:
int m_vie;
int m_mana;
Arme *m_arme;
};
#endif
Voila, j'ai enlevé la déclaration dans Personage.h mais quand je la mettais je me retrouvais avec la même erreur
Une chose sûre : on ne peut pas définir une fonction membre si on ne l'a pas déclarée dans la classe. Il faut donc y remettre la déclaration.
Une chose inquiétante : ton fichier header inclut un fichier cpp. Ça ne doit jamais être effectué, et c'est peut-être la cause de ton problème.
Connais-tu la règle des 3, la règle des 5 et la règle du zéro? C'est en gros une seule et même règle qui dit : Ne jamais jamais jamais gérer soit même les allocations (donc pas de newni de delete). Seul un expert pourrais le faire, et un expert maîtrise forcément la règle des 5. Je suis loin d'être un expert - ça ne fait que trente ans que je pratique le C++ - mais redéfinir l'opérateur d'affectation sans redéfinir le constructeur de copie, je n'ai jamais vu cela.
D'autre part, il y a un bug dans ton opérateur de copie. Il manque entre la ligne 15 et la ligne 16 : m_arme = nullptr;
D'une maniere generale, n'inclus jamais un .cpp dans d'autres fichiers.
Oui mais sans ça il me génère une autre erreur qui là empêche tout fonctionnement alors quand mettant le cpp tout fonctionnait.
Resultat :
C:\Users\Moi\AppData\Local\Temp\ccRqNmRv.o: In function `main':
c:/TP/Heritage/main.cpp:8: undefined reference to `Personnage::Personnage(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int)'
c:/TP/Heritage/main.cpp:10: undefined reference to `Personnage::Personnage(Personnage const&)'
c:/TP/Heritage/main.cpp:13: undefined reference to `Personnage::Personnage()'
c:/TP/Heritage/main.cpp:15: undefined reference to `Personnage::coupDePoing(Personnage&) const'
c:/TP/Heritage/main.cpp:13: undefined reference to `Personnage::~Personnage()'
c:/TP/Heritage/main.cpp:10: undefined reference to `Personnage::~Personnage()'
c:/TP/Heritage/main.cpp:8: undefined reference to `Personnage::~Personnage()'
c:/TP/Heritage/main.cpp:13: undefined reference to `Personnage::~Personnage()'
c:/TP/Heritage/main.cpp:10: undefined reference to `Personnage::~Personnage()'
C:\Users\Moi\AppData\Local\Temp\ccRqNmRv.o:c:/TP/Heritage/main.cpp:8: more undefined references to `Personnage::~Personnage()' follow
collect2.exe: error: ld returned 1 exit status
The terminal process terminated with exit code: 1
Dalfab a écrit:
Connais-tu la règle des 3, la règle des 5 et la règle du zéro? C'est en gros une seule et même règle qui dit : Ne jamais jamais jamais gérer soit même les allocations (donc pas de newni de delete). Seul un expert pourrais le faire, et un expert maîtrise forcément la règle des 5.
Je suis un cours qui nous demande de les utiliser, moi je suis juste le cours et il ne parle pas "des règles 0, 3, 5 ?"
En c++, la compilation passe essentiellement par 2 phases:
La compilation d'un .cpp en .o
Le regroupement de tous les .o en un exécutable
Les erreurs de référence indéfinie sont dues à la seconde phase: les fonctions ne sont trouvées dans aucun .o. Ce qui veut dire soit que Personnage.cpp n'est pas compilé, soit que certaines fonctions ne sont pas implémentées.
Montre tous tes fichiers, ce sera plus simple pour nous.
Main.cpp
#include "Personnage.h"
#include <string>
using namespace std;
int main()
{
Personnage goliath("Epée aiguisée", 20);
Personnage david(goliath);
//On crée david à partir de goliath. david sera une « copie » de goliath.
Personnage gontran;
gontran = david;
gontran.coupDePoing(goliath);
return 0;
}
Personnage.cpp
#include "Personnage.h"
#include <iostream>
Personnage::Personnage() : m_vie(100), m_mana(100), m_arme(0)
{
m_arme = new Arme();
}
Personnage::Personnage(string nomArme, int degatsArme) : m_vie(100), m_mana(100), m_arme(0)
{
m_arme = new Arme(nomArme, degatsArme);
}
Personnage::Personnage(Personnage const& personnageACopier)
: m_vie(personnageACopier.m_vie), m_mana(personnageACopier.m_mana), m_arme(0)
{
m_arme = new Arme(*(personnageACopier.m_arme));
}
void Personnage::recevoirDegats(int degats)
{
m_vie -= degats;
cout << m_vie << endl;
}
void Personnage::coupDePoing(Personnage &cible) const
{
cible.recevoirDegats(m_arme->getDegats());
}
Personnage& Personnage::operator=(Personnage const& personnageACopier) //Quand on fait david = gontran
{
if (this != &personnageACopier) //On verifie qu'on fait pas gontran = gontran
{
m_vie = personnageACopier.m_vie;
m_mana = personnageACopier.m_mana;
delete m_arme; //On supprime le lien entre le nouveau personnage et l'adresse de l'arme du gars qu'on copiess
m_arme = new Arme(*(personnageACopier.m_arme));
}
return *this;
}
Personnage::~Personnage()
{
delete m_arme;
}
Personnage.h
#ifndef DEF_PERSONNAGE
#define DEF_PERSONNAGE
#include <iostream>
#include <string>
#include "Arme.h"
class Personnage
{
public:
Personnage();
Personnage(std::string nomArme, int degatsArme);
Personnage(Personnage const& personnageACopier);
void recevoirDegats(int degats);
void coupDePoing(Personnage &cible) const;
~Personnage();
private:
int m_vie;
int m_mana;
Arme *m_arme;
};
#endif
#ifndef DEF_ARME
#define DEF_ARME
#include <iostream>
#include <string>
class Arme
{
public:
//Methodes
Arme();
Arme(std::string nom, int degats);
void changer(std::string nom, int degats);
void afficher() const;
int getDegats() const;
private:
//Attributs
std::string m_nom;
int m_degats;
};
#endif
jo_link_noir a écrit:
En c++, la compilation passe essentiellement par 2 phases:
La compilation d'un .cpp en .o
Le regroupement de tous les .o en un exécutable
Les erreurs de référence indéfinie sont dues à la seconde phase: les fonctions ne sont trouvées dans aucun .o. Ce qui veut dire soit que Personnage.cpp n'est pas compilé, soit que certaines fonctions ne sont pas implémentées.
C'était d'ailleurs pour ça que j'avais include les .cpp
Oui mais sans ça il me génère une autre erreur qui là empêche tout fonctionnement alors quand mettant le cpp tout fonctionnait.
C'est pas une raison pour faire n'importe quoi.
Les erreurs, elles ont des causes. Il faut les rechercher, et comprendre, et rectifier correctement. Sinon, tant qu'on n'a pas compris, elles se reproduisent constamment. Sales betes.
Les erreurs, elles ont des causes. Il faut les rechercher, et comprendre, et rectifier correctement. Sinon, tant qu'on n'a pas compris, elles se reproduisent constamment. Sales betes.
Oui mais je pensais que c'était comme ça car l'erreur était partie et tout fonctionnait
Par contre ton code fait parti des classiques erreur de débutants. Un personnage a une sémantique d'entité, il n'est pas censé être copiable car il est unique.
Et d'ailleurs la copie d'arme est aussi à perte car faire une copie polymorphique n'est pas aussi simple que ça (d'où le fait de ne pas copier).
git is great because Linus did it, mercurial is better because he didn't.
Je sais qu'il fait parti des erreurs de débutant car j'en suis un. Je suis même pas encore à la moitié du cours d'OCR (au moment où on essaye de copier justement) bref je suis toujours un peu bloqué jusque ici :/
Comme dit precedemment plusieurs fois, un de tes fichiers cpp n'est probablement pas compilé. Verifie dans ton systeme de build (celui de Code Blocks?) que tous les fichiers .cpp sont bien listés.
D'accord j'ai inclut tous les .cpp dans ma commande g++ et ça a marché ^^'
Désolé de vous avoir dérangé, merci beaucoup.
Ce n'est pas la manière de faire. C'est ok pour des petits programmes mais lorsqu'on travaille avec une application ayant des milliers de fichiers on utilise un vrai système de build (CMake ou Make au minimum).
git is great because Linus did it, mercurial is better because he didn't.
D'accord j'ai inclut tous les .cpp dans ma commande g++ et ça a marché ^^'
Désolé de vous avoir dérangé, merci beaucoup.
Ce n'est pas la manière de faire. C'est ok pour des petits programmes mais lorsqu'on travaille avec une application ayant des milliers de fichiers on utilise un vrai système de build (CMake ou Make au minimum).
Je ne sais pas comment faire un vrai système de build avec CMake ou Make mais bon pour l'instant ça me suffit grandement pour mon cours.
En supposant que tu découpes ton projet qu'on appellerait "LearnCpp" en un sous-répertoire par exercice, tu pourrais écrire un fichier CMakeLists.txt à la racine du projet comme ceci:
Si ton IDE a une intégration de CMake, tu voudras surement ajouter les fichiers header dans le add_executable, pour que le linter et l'autocomplétion s'y retrouvent, mais en soit pour la compilation ça n'a pas d'importance.
Si tu fais un nouvel exercice, hop un nouveau répertoire "exercise02" et tu ajoutes dans le même fichier CMakeLists.txt un add_executable.
En théorie, si tu apprends le C++ avec un cours sérieux, tu vas te retrouver avec des centaines d'exercices (C++ Primer doit en avoir pas loin d'un millier je crois). Donc un bon système de build te permet de bien décrire tout ce bazar en un ou plusieurs fichiers très clairs, et revenir plus tard sur un vieil exercice facilement (et même avec un autre compilateur ou OS).
De toute façon, à un moment donné tu sentiras bien qu'il faut ajouter une couche d'abstraction à ton build pour te simplifier la vie.
error: definition of implicitly-declared
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
En recherche d'emploi.
git is great because Linus did it, mercurial is better because he didn't.
git is great because Linus did it, mercurial is better because he didn't.