Résultat surprenant

Résolu
cs_thomas71 Messages postés 13 Date d'inscription mercredi 29 juin 2005 Statut Membre Dernière intervention 4 juillet 2012 - 4 juil. 2012 à 20:54
yann_lo_san Messages postés 1137 Date d'inscription lundi 17 novembre 2003 Statut Membre Dernière intervention 23 janvier 2016 - 5 juil. 2012 à 13:21
Bonjour,

j'ai écrit ce code afin de m'entraîner à utiliser les classes. Cependant, il produit un résultat inattendu et je n'arrive pas à trouver l'origine du problème. Le code est le suivant :

#include 
#include <cmath>

using namespace std;

class point
{
public:
    point(int abscisse, int ordonnee)
    {
        x = abscisse;
        y = ordonnee;
    };
    int abscisse() {return x; }
    int ordonnee() {return y; }

private:
int x;
int y;
};

class segment
{
  public:
    segment(point a, point b)
    {
        debut = &a;
        fin = &b;
    };

    double l1()
    {
        return debut->abscisse();
    }

 double l2()
    {
        return debut->ordonnee();
    }

 double l3()
    {
        return fin->abscisse();
    }

 double l4()
    {
        return fin->ordonnee();
    }

  private:
  point * debut;
  point * fin;
};

int main()
{
    point a(1,2), b(3,4);
    segment ab(a,b);
    cout << "Abscisse de a : " << a.abscisse() << ", ordonnee de a : " << a.ordonnee() << endl;
    cout << "Abscisse de b : " << b.abscisse() << ", ordonnee de b : " << b.ordonnee() << endl;
    cout << "Longueur de [ab] : " << ab.l1() << " " << ab.l2() << " " << ab.l3() << " " << ab.l4();
    return 0;
}


J'obtiens ceci en sortie :
Abscisse de a : 1, ordonnee de a : 2
Abscisse de b : 3, ordonnee de b : 4
Longueur de [ab] : 4.61813e+006 2 3 4


Normalement, il devrait retourner : Longueur de [ab] : 1 2 3 4

Merci de votre aide!

4 réponses

cptpingu Messages postés 3837 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 28 mars 2023 123
4 juil. 2012 à 23:02
Bonjour.

Tout d'abord:
- Évite les "using namespace", voir: http://0217021.free.fr/portfolio/axel.berardino/articles/bon-usage-using-namespace
- Met une majuscule au classe et un _ devant les attributs de classe (genre "int _x;")
- cmath ne te sert à rien ici.
- Évite de coder dans un header, directement dans ta classe.

yann_lo_san t'as déjà décrit l'origine du problème, je n'y reviendrais donc pas. Il est, de manière générale, dangereux de prendre l'adresse d'une valeur temporaire.

je me demande pourquoi ce problème se produit pour a.abscisse() et pas pour b.abscisse()..

Coup de chance, ça dépend de l'état de la mémoire à un instant t. Une valeur détruite ne l'est pas pour de vrai, elle est marquée comme étant réinscriptible. Si par chance aucun processus n'a réécrit par dessus, tu auras la bonne valeur (mais aucune garantie forte).


@yann_lo_san: Pas tout à fait d'accord avec deux choses (vraiment des petits détails, ton explication étant tout à fait correcte):

segment(const point& a, const point& b)
{
debut = new Point(a.abscisse(), a.ordonnee());
fin = new Point(b.abscisse(), b.ordonnee());
};

Dans ce cas, autant laisser "point a" en arguemnt et mettre comme attributs des "point" au lieu de "point*". La gestion est alors automatique pour un résultat similaire à ce que tu proposes.


~segment()
{
if(debut) delete debut;
if(fin) delete fin;
}

Les "if" ne servent à rien ici. "delete 0" est tout à fait valide et ne fait rien. delete est une fonction qui vérifie déjà si le pointeur est nul.

________________________________________________________________________
Historique de mes créations, et quelques articles:
[ http://0217021.free.fr/portfolio http://0217021.free.fr/portfolio]
Merci d'utiliser Réponse acceptée si un post répond à votre question
3
yann_lo_san Messages postés 1137 Date d'inscription lundi 17 novembre 2003 Statut Membre Dernière intervention 23 janvier 2016 26
4 juil. 2012 à 21:43
Salut,

tu passes des "point" valeurs qui sont détruits à l'accolade fermante du constructeur,
tu devrais essayer ceci :

segment(point* a, point* b)
{
    debut = a;
    fin = b;
};


et

point a(1,2), b(3,4);
segment ab(&a, &b);


Mais il serait plus propre d'utiliser des références :

segment(const point& a, const point& b)
{
    debut = new Point(a.abscisse(), a.ordonnee());
    fin = new Point(b.abscisse(), b.ordonnee());
};

// et utiliser un destructeur

~segment()
{
    if(debut) delete debut;
    if(fin) delete fin;
} 



bye...
0
cs_thomas71 Messages postés 13 Date d'inscription mercredi 29 juin 2005 Statut Membre Dernière intervention 4 juillet 2012
4 juil. 2012 à 22:30
Merci pour ton aide mais en fait je me demande pourquoi ce problème se produit pour a.abscisse() et pas pour b.abscisse()...
0
yann_lo_san Messages postés 1137 Date d'inscription lundi 17 novembre 2003 Statut Membre Dernière intervention 23 janvier 2016 26
5 juil. 2012 à 13:21
Salut,

tout à fait d'accord avec toi CptPingu.

2 questions simples à se poser pour l'agrégation :

- Vais-je modifier l'état de l'objet dans ma classe ?
- Dois-je copier l'objet pour que les changements d'état n'affectent pas l'objet original "venu de l'extérieur".

D'ou le choix entre pointeur, référence constante et référence non constante, et la prise de décision quant à la copie d'un objet.

Attention au "gros objets" copiés sur la pile.

hummm... gros objets, pile..., intéressant comme concept.

bye...
0
Rejoignez-nous