1. #1
    Membre du Club
    Homme Profil pro
    Etudiant
    Inscrit en
    novembre 2015
    Messages
    113
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 26
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Etudiant

    Informations forums :
    Inscription : novembre 2015
    Messages : 113
    Points : 49
    Points
    49

    Par défaut Comment utiliser les fonctions amies pour Simuler les points de l'espace Rn?

    Bonjour ! J'ai déjà un bagage en programmation orientée objet, j'ai déjà suivi un an de cours de java.
    Les questions qui suivent sont donc celles d'un débutant en C++. J'essaye de faire une annale d'exament sur la simulation de points dans l'espace Rn. J'ai mis l'annale en pièce jointe. Il s'agit du deuxième exercice : voici les questions qui me posent problème et mes tentatives :

    J'ai du mal avec les fonctions amies et j'ai déjà un problème en mettant la calsse PointRn comme public.

    Ecrire une classe cannonique PointRn simulant les points de Rn avec:
    deux attributs privés int dim et double* adr ,
    • un constructeur,
    • un destructeur,
    • un constructeur de recopie,
    • l'opérateur = .
    J'ai tout fait même le constructeur de recopie, c'est la première fois que j'en ai un, je sais que ca sert à copier un objet ou faire des template.

    Munir la classe PointRn des opérateurs == , != , * , + en tant que fonctions amies.
    Mais du coup :

    • Comment on additionne/multiplie des points ?
    • C'est quoi la différence d'== avec = ?


    On me demande ensuite :

    D'Ecrire une classe abstraite boule avec: deux attributs privés PointRn centre et double rayon , et une fonction membre bool contient(point p) .
    Dois-je l'écrire dans un deuxième fichier ?

    Voici mon code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    #import<iostream>
     
    using namespace std;
     
    public class PointRn(){
     
    	private int dim;
    	private double* adr;
     
    	PointRn(int dim, double* adr){
    		cout << "Constructeur de PointRn.\n";
    		this.dim = dim;
    		this.adr = adr;
    	}
     
    	PointRn(const PointRn &){
    		cout << "Constructeur de recopie de PointRn.\n";
    	}
     
     
    	// Comment fait on un destructeur ?
    	~PointRn(){
    		cout << "Destructeur de PointRn.\n";
    	}
     
    	PointRn operator = (PointRn, PointRn);
    	// Comment on additionne/multiplie des points ?
    	friend PointRn operator + (PointRn, PointRn);
    	friend PointRn operator * (PointRn, PointRn);
    	// C'est quoi la différence avec = ?
    	friend bool operator == (PointRn, PointRn);
    	friend bool operator != (PointRn, PointRn);
     
    }
     
    PointRn operator +(PointRn,PointRn){
     
    }
     
    PointRn operator *(PointRn,PointRn){
     
    }
     
    PointRn operator ==(PointRn,PointRn){
     
    }
     
    PointRn operator !=(PointRn,PointRn){
     
    	return ();
     
    }
     
     
     
    int main(){
     
    }
    Images attachées Images attachées

  2. #2
    Membre chevronné
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    décembre 2015
    Messages
    396
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : décembre 2015
    Messages : 396
    Points : 1 752
    Points
    1 752

    Par défaut

    Bonjour,

    Attention, ton code semble être un hybride entre du C++ et du Java.
    J'ai tout fait même le constructeur de recopie, c'est la première fois que j'en ai un, je sais que ca sert à copier un objet ou faire des template.
    Ca sert à construire un objet à partir d'un modèle du même type.
    • Comment on additionne/multiplie des points ?
    En effet, bonne question qui devrait être dans l'énoncé!
    • C'est quoi la différence d'== avec = ?
    L'opérateur de copie est utilisé pour effectuer une copie (à ne pas confondre avec le contructeur par copie), il doit être une fonction membre et devrait retourner une référence à l'objet. L'opérateur d'égalité lui retourne un booléen qui indique si les 2 objets sont égaux, il peut être défini comme une fonction membre (avec 1 paramètre) ou comme un fonction non membre(avec 2 paramètres).
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    class PointRn {
       ...
    public:
       PointRn& operator =( const PointRn& );
       friend bool operator==( const PointRn& , const PointRn& );
       ...
    };
    // operateur membre de copie
    PointRn& PointRn::operator=( const PointRn& src ) {
       if ( this != &src ) { // N'est pas une copie de soit-même!
          // met à jour l'objet courant à partir du modèle
          // copier les éléments de src vers this ...
       }
       return *this; // on retourne une référence à l'objet
    }
    // operateur non membre d'égalité
    bool operator==( const PointRn& pta , const PointRn& ptb  ) {
       // retourne si pta et ptb sont égaux ...
    }

  3. #3
    Membre du Club
    Homme Profil pro
    Etudiant
    Inscrit en
    novembre 2015
    Messages
    113
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 26
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Etudiant

    Informations forums :
    Inscription : novembre 2015
    Messages : 113
    Points : 49
    Points
    49

    Par défaut

    Merci pour votre aide !
    Je pense aussi qu'il y a un mélange entre C++ et Java d'abord. J'ai encore plein d'erreur et je ne suis pas très sûr de mon constructeur qui ressmeble à du Java.

    Ensuite, je suis en train d'apprendre les référence. Pourquoi en avoir mise une ici ? Et pourquoi const ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     PointRn& operator = (const PointRn);

  4. #4
    Membre émérite
    Inscrit en
    mars 2005
    Messages
    823
    Détails du profil
    Informations forums :
    Inscription : mars 2005
    Messages : 823
    Points : 2 309
    Points
    2 309

    Par défaut

    La dimension du vecteur en donnée membre plutôt qu'en paramètre template.. pourquoi pas !

    Citation Envoyé par AntoineCompagnie Voir le message
    • Comment on additionne/multiplie des points ?
    Citation Envoyé par dalfab Voir le message
    En effet, bonne question qui devrait être dans l'énoncé!
    Oui j'aimerais bien savoir comment on additionne un vecteur de dimension m et un autre de dimension n. Je comprends bien qu'il n'est pas toujours nécessaire que les exercices aient un sens, mais tout de même..

  5. #5
    Membre chevronné
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    décembre 2015
    Messages
    396
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : décembre 2015
    Messages : 396
    Points : 1 752
    Points
    1 752

    Par défaut

    Citation Envoyé par AntoineCompagnie Voir le message
    Ensuite, je suis en train d'apprendre les référence. Pourquoi en avoir mise une ici ? Et pourquoi const ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     PointRn& operator = (const PointRn &);
    Passer de Java à C++ ne peut se faire qu'à travers un cours C++ car il y a de nombreuses choses qui se ressemblent et sont piégeuses.
    L'opérateur reçoit un objet par l-référence constante, car on n'utilisera le modèle que pour le lire (const) et qu'il n'y peut-être pas d'intérêt à recevoir une copie d'objet (l-référence). La fonction doit retourner une l-référence à l'objet courant, cela permet un enchaînement d'affectations. a = b = c; sera équivalent à b = c; a = b; car b = c retourne une l-référence sur b.
    On pourrait aussi écrire l'opérateur de copie sous la forme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    PointRn& PointRn::operator=( PointRn pt ) {
       swap( *this , pt ); // pt est ici une copie, *this reçoit pt, pt reçoit this.
       return *this; // on retourne un référence sur *this, et le paramètre pt peut disparaître
    }

  6. #6
    Membre éprouvé
    Avatar de Pyramidev
    Homme Profil pro
    Développeur
    Inscrit en
    avril 2016
    Messages
    278
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur

    Informations forums :
    Inscription : avril 2016
    Messages : 278
    Points : 1 149
    Points
    1 149

    Par défaut

    Citation Envoyé par AntoineCompagnie Voir le message
    Comment on additionne/multiplie des points ?
    Pour l'addition :
    • Si les points ont la même dimension, additionne membre à membre.
    • Si les points n'ont pas la même dimension :
      • Si tu as vu les exceptions en C++, lance une exception de type std::domain_error.
      • Sinon, dans ta tête, complète par des 0 le point qui a la dimension la plus petite avant d'additionner. Par exemple, (1, 5, 7, 9) + (2, 1) == (1, 5, 7, 9) + (2, 1, 0, 0) == (3, 6, 7, 9).


    Pour le produit, en l'absence de précision de l'énoncé, tu peux faire un produit scalaire canonique.
    Si les points n'ont pas la même dimension, même remarque que pour l'addition.

    A part ça, l'exercice 3 encourage de mauvaises pratiques sur la gestion de la mémoire. Normalement, on utilise std::vector.

  7. #7
    Membre du Club
    Homme Profil pro
    Etudiant
    Inscrit en
    novembre 2015
    Messages
    113
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 26
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Etudiant

    Informations forums :
    Inscription : novembre 2015
    Messages : 113
    Points : 49
    Points
    49

    Par défaut

    Merci pour toutes vos réponses ! Avec quelques recherche j'ai retravaillé le code pour qu'il compile au moins. Cependant il est encore un peu vide :

    • Qu'est ce que j'additionne ? Je n'ai qu'une dimension et une adresse comme paramètres ...
    • Ou dois-je créer la classe abstraite boule dans un fichier à part ? J'ai pris le partie de le faire dans le fichier


    Il s'agit d'écrire une classe abstraite boule avec: deux attributs privés PointRn
    centre et double rayon , et une fonction membre bool contient(point p) .
    Néanmoins j'ai un problème à l'écriture de la fonction de la classe abstraite : bool contient(point p). point n'est pas déclaré ici... J'ai essayé PointRn mais c'est pas mieux...


    PS: je comprends qu'en évitant d'utiliser vector je ne prends pas de bonnes habitudes... Pourriez-vous, si vous avez le temps me montrer comment on les utilise pour que je puisse faire une deuxième version du code plus orthodoxe ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    #import<iostream>
     
    using namespace std;
     
    class PointRn{
     
    	public:
    		PointRn(int dim, double* adr);
    		PointRn(const PointRn &);
     
     
    	private:
    		int dim;
    		double* adr;
     
    	~PointRn(){
    		cout << "Destructeur de PointRn.\n";
    	}
     
    	public:
    		PointRn& operator = (const PointRn);
    		// Comment on additionne/multiplie des points ?
    		friend PointRn operator + (PointRn, PointRn);
    		friend PointRn operator * (PointRn, PointRn);
    		// C'est quoi la différence avec = ?
    		friend bool operator == (PointRn, PointRn);
    		friend bool operator != (PointRn, PointRn);
     
    };
     
    PointRn operator +(const PointRn& pta , const PointRn& ptb){
                   // à compléter
    }
     
    PointRn operator *(const PointRn& pta , const PointRn& ptb){
                   // à compléter               
    }
     
    bool operator ==(const PointRn& pta , const PointRn& ptb){
                   // à compléter
    }
     
    bool operator !=(const PointRn& pta , const PointRn& ptb){
                   // à compléter
    }
     
     
     
    int main(){
     
    }

  8. #8
    Expert éminent
    Homme Profil pro
    Développeur informatique
    Inscrit en
    février 2005
    Messages
    4 136
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : février 2005
    Messages : 4 136
    Points : 8 734
    Points
    8 734

    Par défaut

    Un peu de rigueur, SVP.

    bool contient(point p). point n'est pas déclaré ici... J'ai essayé PointRn mais c'est pas mieux...
    "point", on le connait ni d'Eve ni des dents, le compilateur non plus, c'est normal qu'il gueule.
    "PointRn", vous avez bien fait une forward déclaration de la classe "PointRn" ou ajouter un include du .h ayant la déclaration de cette classe ?
    En plus, la signature de cette méthode est RIDICULE, elle n'a pas besoin d'une copie du paramètre pour travailler:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    bool contient(const PointRn& p){...}
    PS: je comprends qu'en évitant d'utiliser vector je ne prends pas de bonnes habitudes... Pourriez-vous, si vous avez le temps me montrer comment on les utilise pour que je puisse faire une deuxième version du code plus orthodoxe ?
    Vos points ne changeront pas de cardinalité, c'est pas un std::vector mais un std::array qu'il vous faudra utiliser.

  9. #9
    Membre émérite
    Inscrit en
    mars 2005
    Messages
    823
    Détails du profil
    Informations forums :
    Inscription : mars 2005
    Messages : 823
    Points : 2 309
    Points
    2 309

    Par défaut

    Citation Envoyé par bacelar Voir le message
    Vos points ne changeront pas de cardinalité,
    Il s'agit d'une contrainte de l'énoncé d'origine.. Elle est décriée en début de fil.

  10. #10
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    Consultant informatique
    Inscrit en
    octobre 2004
    Messages
    10 373
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Belgique

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : octobre 2004
    Messages : 10 373
    Points : 22 014
    Points
    22 014

    Par défaut

    Salut,

    Juste une petite remarque au passage, pour l'opérateur d'affectation...

    Tu écris
    Citation Envoyé par dalfab Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    // operateur membre de copie
    PointRn& PointRn::operator=( const PointRn& src ) {
       if ( this != &src ) { // N'est pas une copie de soit-même!
          // met à jour l'objet courant à partir du modèle
          // copier les éléments de src vers this ...
       }
       return *this; // on retourne une référence à l'objet
    }
    Fut un temps où quelqu'un avait eu "l'idée de génie" de se poser la question qui tue : mais que se passera-t-il si on écrit un code proche de a = a. Et tout le monde s'est engouffré dans la brêche pour conseiller de faire un test de "non auto affectation".

    Depuis, on s'est rendu compte que c'était pure connerie : très peu de gens voudront écrire un tel code, mais, en plus, il est tout à fait possible de contourner le problème de manière bien plus efficace en ayant recours à l'idiome copy and swap : on crée une copie de l'élément fournit en paramètre, et on interverti les donnée de cette copie avec celles de l'élément qui subit l'affectation, sous une forme qui pourrait être proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
     
    /* Avant, il y avait la règle des trois grands : si on fournit une implémentation personnelle de l'une des 
     * fonctions que sont le constructeur de copie, l'opérateur d'affectation ou le destructeur, il faut fournir
     * l'implémentation des trois.
     *
     * Depuis l'arrivée de C++11, des pointeurs intelligents et de la sémantique de déplacement, elle s'est transformée, selon le cas
     * en règle des 0 (lorsqu'on utilise les pointeurs intelligents) ou en règle des cinq grands, car il faut également prendre en compte
     * le constructeur de copie par déplacement et l'opérateur d'affectation par déplacement.
     *
     * Par facilité, je vais me limiter à la règle des trois grands ;)
     */
    struct Truc{
        // ca, c'est le constructeur de copie
        Truc(Truc const &);
        // ca, c'est l'opérateur d'affectation
       Truc & operator=(Truc const & other);
       // et ca, c'est le destructeur
       ~Truc();
       /* voilà pour la règle des trois grand... ne manque plus que 
        * le deuxième volet du copy and swap : l'échange des données entre
        * deux éléments de type identique
        */
       void swap(Truc & other);
    };
    Je ne vais pas donner l'implémentation du constructeur de copie ni celle du destructeur, elle est beaucoup trop dépendante du contenu de Truc. Par contre, pour ce qui est de la fonction swap (qui est aussi très dépendante du contenu de Truc), on pourrait dire qu'elle correspond à peu près à
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    void Truc::swap(Truc & other){
        /*on utilise std::swap entre toutes les données de other et les données respectives de l'objet courant,
         * par exemple 
         */
        std::swap(a, other.a);
        std::swap(b, other.b);
       /* ... */
    }
    Et, enfin, nous pouvons définir l'opérateur d'affectation, qui va :
    copier l'élément passé en paramètre
    effectuer un swap entre la copie créé et l'objet courant
    sous une forme qui pourrait être proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    Truc & Truc::operator = (Truc const & other){
        /* il y a moyen de le faire en moins de lignes, je montre ici toutes les étapes */
        auto temp{other}; // on copie l'élément donné en paramètre
        temp.swap(*this); // on interverti les donnée de la copie et de l'objet courant
        return *this; // on renvoie une référence sur l'objet courant
    }
    De cette manière, il n'est même plus besoin d'effectuer un test d'auto affectation, vu que l'on travaille, de toutes manières, toujours sur une copie de l'élément fourni en paramètre

    NOTA : oui, je sais : d'aucuns viendront conseiller de transmettre le paramètre de l'opérateur d'affectation par valeur, pour qu'il soit automatiquement copié... Cela ne change pas grand chose dans le cas présent à part que les choses sont plus explicites ici
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

Discussions similaires

  1. Réponses: 1
    Dernier message: 08/04/2014, 20h49
  2. [XL-2003] Comment utiliser la fonction "Actualiser les données"
    Par P96O1004 dans le forum Excel
    Réponses: 10
    Dernier message: 27/05/2009, 15h05
  3. Réponses: 6
    Dernier message: 09/12/2008, 10h45
  4. Réponses: 2
    Dernier message: 06/10/2008, 11h04
  5. Réponses: 8
    Dernier message: 29/06/2006, 16h37

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo