Problème avec le constructeur de copie

razuki Messages postés 293 Statut Membre -  
Char Snipeur Messages postés 10112 Date d'inscription   Statut Contributeur Dernière intervention   -
Bonjour,

J'ai défini un classe Personnage. J'essaie de copier le Personnage goliath vers le Personnage david comme suit :

int main() 
{ 
 Personnage goliath("Epée aiguisée", 20); 
 Personnage david = goliath; 
... 
}


Voici les constructeurs que j'ai crée dans la classe Personnage :

Personnage::Personnage() : m_vie(100), m_mana(100) 
{ 
 m_arme = new Arme(); 
} 
Personnage::Personnage(string nomArme, int degatsArme) : m_vie(100), m_mana(100)
{
	m_arme = new Arme(nomArme, degatsArme);
}


Le compilateur me dit alors :

Undefined reference to 'Personnage::Personage(Personnage const&)


Ma question :
-- Le compilateur ne crée - t - il pas automatiquement le constructeur de copie ?
-- le problème serait - il ailleurs ?

Merci d'avance pour votre aide.
A voir également:

3 réponses

Char Snipeur Messages postés 10112 Date d'inscription   Statut Contributeur Dernière intervention   1 299
 
je sais pour le constructeur par défaut (sans argument) qu'il est fabriqué automatiquement sauf s'il y a un autre constructeur. Il en va peut être de même avec le constructeur par copie.
As tu déclarer le constructeur par copie ?
Met nous le .h de la class que nous puissions nous faire un avis.
0
razuki Messages postés 293 Statut Membre 1
 
En fait je n'ai pas définit le constructeur de copie, je l'ai juste declaré ...
ce problème est résolu.
Un autre problème toujours lié au constructeur de copie :

-- j'ai deux Personnage david et goliath qui ont un pointeur arme pointant vers le meme objet arme (voir main ci-dessus).
-- j'ai détruit david ( d'abord son arme, puis lui meme ), puis j'ai détruit goliath et ceux en fin de main( )

goliath.~Personnage();
david.~Personnage();

Ma question :
est-ce normal que le compilateur ne rale pas, que le programme ne plante pas ... ?
En effet quand je détruit goliath l'arme disparait avec lui. Quand je tente de détruire david, le compilateur est censé cherche son arme ... NON ?

Merci d'avance pour votre aide.
0
Char Snipeur Messages postés 10112 Date d'inscription   Statut Contributeur Dernière intervention   1 299
 
encore une fois, difficile de dire, tu ne mets pas de code. Déjà pour dire il faudrait avoir le destructeur.
Ensuite, le destructeur s'appelle avec "delete" et non avec "~Personnage "
Pour finir il n'y a besoin d'appeler le destructeur qu'en cas d'objet alloué dynamiquement (de pointeur si tu préfères). Et là tu alloue deux objets normaux qui seront détruits automatiquement.

Dans la même veine, mais un peu différent, les membres dynamiques. La règle est simple : tout new correspond à un delete. Tes membres dynamiques ne sont détruit que si tu le fait explicitement dans le destructeur. C'est pour ça que pour répondre, nous avons besoin de morceau de codes.
0
razuki Messages postés 293 Statut Membre 1
 
D'accord. Maintenant je cherche à provoquer un plantage. Arme est un pointeur dans Personnage. Le constructeur de copie que j'ai crée dans Personnage copie le pointeur et non pas l'objet pointé. david et goliath possède alors le meme objet arme. Et je me demande pourquoi ca ne plante pas.

Voici mon code :

Personnage.h
class Personnage
{
    public:
 
	Personnage();
	Personnage(std::string nomArme, int degatsArme);
	Personnage(const Personnage &personnageACopier);
    void recevoirDegats(int nbDegats);
    void attaquer(Personnage &cible);
    void boirePotionDeVie(int quantitePotion);
    void changerArme(std::string nomNouvelleArme, int degatsNouvelleArme);
    bool estVivant();
    void afficherEtat();
 
    ~Personnage();
 
 
    private:
 
    int m_vie;
    int m_mana;
	Arme* m_arme;
    //std::string m_nomArme; // Pas de using namespace std, donc il faut mettre std:: devant string.
    //int m_degatsArme;
 
 
};


Personnage.cpp
//Personnage::Personnage() : m_vie(100), m_mana(100), m_nomArme("Epée rouillée"), m_degatsArme(10) {}
Personnage::Personnage() : m_vie(100), m_mana(100)
{
	m_arme = new Arme();
}
//Personnage::Personnage(string nomArme, int degatsArme) : m_vie(100), m_mana(100), m_arme(nomArme, degatsArme) {}
Personnage::Personnage(string nomArme, int degatsArme) : m_vie(100), m_mana(100)
{
	m_arme = new Arme(nomArme, degatsArme);
}
 
Personnage::Personnage(const Personnage &personnageACopier)
{
    m_vie = personnageACopier.m_vie;
    m_mana = personnageACopier.m_mana;
    m_arme = personnageACopier.m_arme;
    //m_arme = new Arme(personnageACopier.m_arme);
 
}
 
Personnage::~Personnage()
{
	delete m_arme;
}
	void Personnage::recevoirDegats(int nbDegats)
	    {
		m_vie -= nbDegats;
		if (m_vie < 0)
			m_vie = 0;
	    }
		void Personnage::attaquer(Personnage &cible)
		{
			cible.recevoirDegats(m_arme->getDegats());
		}
 
	    void Personnage::boirePotionDeVie(int quantitePotion)
	    {
	    	m_vie += quantitePotion;
	    	if (m_vie > 100)
	    		m_vie = 100;
	    }
 
	    void Personnage::changerArme(std::string nomNouvelleArme, int degatsNouvelleArme)
	    {
	    	m_arme->changer(nomNouvelleArme, degatsNouvelleArme);
 
	    }
 
	    bool Personnage::estVivant()
	    {
	    	if (m_vie > 0)
	    		return true;
	    	else
				return false;
	    }
 
	    void Personnage::afficherEtat()
	    {
	        cout << "Vie : " << m_vie << endl;
	        cout << "Mana : " << m_mana << endl;
	        m_arme->afficher();
	    }


Voici mon main :

int main()
{
    // Création des personnages
    //Personnage david, goliath("Epée aiguisée", 20);
	Personnage goliath("Epée aiguisée", 20);
	Personnage david = goliath;
    // Au combat !
    goliath.attaquer(david);
    david.boirePotionDeVie(20);
    goliath.attaquer(david);
    david.attaquer(goliath);
    goliath.changerArme("Double hache tranchante vénéneuse de la mort", 40);
    goliath.attaquer(david);
 
    // Temps mort ! Voyons voir la vie de chacun...
    cout << "David" << endl;
    david.afficherEtat();
    cout << endl << "Goliath" << endl;
    goliath.afficherEtat();
    //goliath.~Personnage();
    //david.~Personnage();
 
    return 0;
}


Le resultat :
David
Vie : 40
Mana : 100
Arme : Double hache tranchante vénéneuse de la mort (Dégâts : 40)
 
Goliath
Vie : 80
Mana : 100
Arme : Double hache tranchante vénéneuse de la mort (Dégâts : 40)
0
Char Snipeur Messages postés 10112 Date d'inscription   Statut Contributeur Dernière intervention   1 299
 
bon, en effet, tu devrais avoir une erreur ou pas, je ne connais pas le comportement exact de "delete". J'ai trouvé ça qui donne un début de piste (cf. à partir du message de int21h) : https://openclassrooms.com/forum/sujet/c-new-delete-vs-mallocfree-68854
Il est possible que le delete vérifie ce qu'il a à détruite avant de le faire.
plusieurs tests possible, modifier le destructeur :
Personnage::~Personnage()
{
        cout<<"suppresion de l'arme stockée là : "<<(long)m_arme;
	delete m_arme;
}

modifier tes david et goliath par des pointeurs et utiliser directement le delete.
Bonne chance.
0