IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

fonctions amies (compilation)


Sujet :

C++

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    57
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2004
    Messages : 57
    Par défaut fonctions amies (compilation)
    Bonjour à tous !

    Je désire créer une classe en redéfinissant l'opérateur d'addition. Je mets donc ceci dans le .h :
    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
     
    #include <list>
    #include <sstream>
     
    using namespace std;
     
     
    class BigInt  
    {
    public:
    	BigInt();
    	BigInt(const int& n);
    	virtual ~BigInt();
     
    	BigInt& operator =(const int& n);
    	bool operator >(const int& n);
    	bool operator >(const BigInt& bi);
     
    	friend BigInt operator+(const BigInt& a, const BigInt& b);
     
    private:
    	list<int> nombre;
    };
    et dans le .cpp :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    BigInt operator+(const BigInt& a, const BigInt& b) 
    {
    	BigInt res;
     
    	list<int>::const_reverse_iterator it1 = a.nombre.rbegin();
    	list<int>::const_reverse_iterator it2 = b.nombre.rbegin();
     
    	return res;
    }
    Lors de la compilation, j'ai l'erreur suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    D:\mfc\fichusnombres\BigInt.cpp(74) : error C2248: 'nombre' : cannot access private member declared in class 'BigInt'
            D:\mfc\fichusnombres\BigInt.h(21) : see declaration of 'nombre'
    Pourtant la fonction est bien déclarée comme amie... que faire ?

  2. #2
    Membre Expert

    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 294
    Détails du profil
    Informations personnelles :
    Localisation : Royaume-Uni

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 294
    Par défaut
    Salut,

    Est-ce que BigInt ne serait pas dans un namespace par hasard ?

    MAT.

  3. #3
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 466
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 466
    Par défaut
    Citation Envoyé par TheShade Voir le message
    Pourtant la fonction est bien déclarée comme amie... que faire ?
    En premier lieu, si tu as recours à friend dans un projet élémentaire, c'est probablement que tu t'es trompé quelque part.

    Ensuite, si tu utilises l'opérateur + avec deux arguments, c'est pour utiliser la fonction dans l'espace de nommage général, donc il faudrait utiliser l'opérateur de portée :: pour spécifier cette fonction. Dans ton code, tu rends amie une des méthodes de ta classe, ce qui ne sert à rien.

    Enfin, si tu veux faire X + Y entre deux BigInt, étant donné que X en est déjà un, « + » est considéré comme une méthode lui appartenant, et Y son unique argument. Moralité, tu vires « friend », tu vires « const Bigint & a », tu fais l'addition entre l'instance de ton objet et « b », et ça devrait fonctionner.

  4. #4
    Membre éclairé Avatar de befalimpertinent
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    561
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Gironde (Aquitaine)

    Informations forums :
    Inscription : Avril 2007
    Messages : 561
    Par défaut
    Ton exemple devrait marcher. Quel compilateur utilises tu ?
    En premier lieu, si tu as recours à friend dans un projet élémentaire, c'est probablement que tu t'es trompé quelque part.
    Parfois il est utile de faire une opération addition symétrique, une fonction externe à la classe le permet et friend est souvent nécéssaire dans ce cas.
    D'ailleurs un des rare cas ou il est techniquement acceptable.

  5. #5
    Membre confirmé Avatar de zabibof
    Inscrit en
    Février 2007
    Messages
    188
    Détails du profil
    Informations forums :
    Inscription : Février 2007
    Messages : 188
    Par défaut
    Citation Envoyé par Obsidian Voir le message
    Dans ton code, tu rends amie une des méthodes de ta classe
    Euh...

    Citation Envoyé par Obsidian
    Enfin, si tu veux faire X + Y entre deux BigInt, étant donné que X en est déjà un, « + » est considéré comme une méthode lui appartenant, et Y son unique argument.
    C'est moi qui ne comprend rien ou c'est toi qui dis n'importe quoi là

    Citation Envoyé par TheShade
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    BigInt operator+(const BigInt& a, const BigInt& b) 
    {
    	BigInt res;
     
    	list<int>::const_reverse_iterator it1 = a.nombre.rbegin();
    	list<int>::const_reverse_iterator it2 = b.nombre.rbegin();
     
    	return res;
    }
    Je ne sais pas où tu veux en venir avec ce code (bon, peut-être que ce n'est pas le code complet)

    Sinon, normalement, si tu déclares un opérateur global ami d'une classe, elle devrait pouvoir accéder à ses membres non-publiques, donc, c'est sûrement autre chose

  6. #6
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 466
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 466
    Par défaut
    Citation Envoyé par befalimpertinent Voir le message
    Parfois il est utile de faire une opération addition symétrique, une fonction externe à la classe le permet et friend est souvent nécéssaire dans ce cas. D'ailleurs un des rare cas ou il est techniquement acceptable.
    Je suis d'accord, mais dans le cas présent, il utilise « BigInt & » des deux côtés, alors pourquoi ?

  7. #7
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Bonjour,
    Avec VC++ Express et gcc (sous windows), chez moi, ton exemple compile parfaitement. La vérité est ailleurs.

  8. #8
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 466
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 466
    Par défaut
    Citation Envoyé par zabibof Voir le message
    Euh...
    C'est moi qui ne comprend rien ou c'est toi qui dis n'importe quoi là
    Erreur de ma part, effectivement. J'avais un peu trop l'habitude d'utiliser l'opérateur de portée pour atteindre d'autres méthodes. À ma décharge, j'ai posté tard et je n'utilise friend que très rarement.

    Par contre, reconnais qu'utiliser l'opérateur global pour additionner deux membres d'une même classe n'a aucun intérêt dans le cas présent. Tu n'es pas d'accord ?

  9. #9
    screetch
    Invité(e)
    Par défaut
    peut etre en la declarant avant, pour etre sur que les namespace, etc... convergent

    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
     
    BigInt operator+(const BigInt& a, const BigInt& b);
     
    class BigInt  
    {
    public:
    	BigInt();
    	BigInt(const int& n);
    	virtual ~BigInt();
     
    	BigInt& operator =(const int& n);
    	bool operator >(const int& n);
    	bool operator >(const BigInt& bi);
     
    	friend BigInt operator+(const BigInt& a, const BigInt& b);
     
    private:
    	list<int> nombre;
    };

  10. #10
    Membre confirmé Avatar de zabibof
    Inscrit en
    Février 2007
    Messages
    188
    Détails du profil
    Informations forums :
    Inscription : Février 2007
    Messages : 188
    Par défaut
    Citation Envoyé par Obsidian Voir le message
    Par contre, reconnais qu'utiliser l'opérateur global pour additionner deux membres d'une même classe n'a aucun intérêt dans le cas présent. Tu n'es pas d'accord ?
    Ben non , si c'était l'opérateur +=, je serais d'accord. Moi, je surcharge toujours l'opérateur + en global mais bon, à chacun ses méthodes

  11. #11
    Membre Expert
    Homme Profil pro
    edi
    Inscrit en
    Juin 2007
    Messages
    940
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : edi

    Informations forums :
    Inscription : Juin 2007
    Messages : 940
    Par défaut
    Citation Envoyé par Obsidian Voir le message
    En premier lieu, si tu as recours à friend dans un projet élémentaire, c'est probablement que tu t'es trompé quelque part.
    Je ne vois pas exactement en quoi ; ça me paraît ici tout à fait cohérent avec ce qu'il développe. L'autre solution serait d'avoir un accesseur à la liste, mais ici je ne crois pas que se serait pertinent.

    Citation Envoyé par Obsidian Voir le message
    Ensuite, si tu utilises l'opérateur + avec deux arguments, c'est pour utiliser la fonction dans l'espace de nommage général, donc il faudrait utiliser l'opérateur de portée :: pour spécifier cette fonction.
    Pourquoi aurait-on besoin de '::' ?

    Citation Envoyé par Obsidian Voir le message
    Dans ton code, tu rends amie une des méthodes de ta classe, ce qui ne sert à rien.
    Laquelle ? La seule fonction amie ici est également la seule fonction qui ne soit pas une méthode de classe, justement.

    Citation Envoyé par Obsidian Voir le message
    Enfin, si tu veux faire X + Y entre deux BigInt, étant donné que X en est déjà un, « + » est considéré comme une méthode lui appartenant, et Y son unique argument. Moralité, tu vires « friend », tu vires « const Bigint & a », tu fais l'addition entre l'instance de ton objet et « b », et ça devrait fonctionner.
    C'est vrai que ça pourrait marcher, mais normalement, on ne fait pas comme ça, pour des questions d'arité, de symétrie ; il y a même, me semble-t-il, tout un paragraphe de la Faq qui y est consacré.

    Concrètement, c'est la différence entre 'a+=b, et 'c = a + b'. Dans le premier cas, '+=' peut s'utiliser seul, et a un sens, l'objet 'a' est central dans cette opération. Mais '+' n'a aucun sens seul : on ne fait pas 'a + b', mais 'c = a + b', l'opérateur doit être combiné à autre chose ; de plus, on peut voir que 'a' n'est pas central au traitement, on prend des objets, qui ont la même importance, afin d'en créer un 3ème. D'ailleurs, '+=' renvoie l'objet sur lequel a été effectuée l'opération, alors que '+' renvoie un objet nouveau.

    De plus, '+' est définit ici pour des BigInt, mais il pourrait combiner un BigInt et un int. Or, avec '+', tu peux faire 'a + b', mais aussi 'b + a'. Si tu définit 'operator+' en méthode de classe, 'BigInt + int' est correct, mais 'int + BigInt' ne l'est pas, ce qui est opposé au sens intuitif de cet opérateur. D'ailleurs, il faudrait définir les deux fonctions :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    BigInt operator+(const BigInt& b, int i);
    BigInt operator+(int i, const BigInt& b);
    Par contre, selon ce principe, les opérateurs de comparaison (bool operator <) devraient aussi être des fonctions extérieures, et non des méthodes de classe.

    Il y a 2 choses sinon qui me préoccupent :

    Est-ce-que l'on doit pouvoir hériter de ta classe ? Je n'en ai pas l'impression, et dans ce cas tu devrais pas mettre le destructeur en virtual.

    Ceci veut dire que tu as fait 'using namespace std;' dans le .h de ta classe, et c'est quelque chose à éviter.

    A part ça, je ne comprends pas que ça ne compile pas. Ton code m'a l'air correct, et sur ma machine ça compile sans problème, à mon avis ça doit venir d'autre part .

Discussions similaires

  1. [SQL2005][TSQL] Problème de curseur / Fonction ne "compile" pas
    Par Ivenoproblemwiththat dans le forum MS SQL Server
    Réponses: 3
    Dernier message: 01/06/2007, 21h55
  2. Fonction ami + template
    Par zenux dans le forum Langage
    Réponses: 8
    Dernier message: 08/12/2006, 15h59
  3. fonctions amies
    Par Vips dans le forum C++
    Réponses: 10
    Dernier message: 24/03/2006, 04h41
  4. fonctions amies
    Par hamma2 dans le forum C++
    Réponses: 4
    Dernier message: 10/12/2005, 20h19
  5. [C++] Fonction amie vituelle dans une classe ?
    Par Bob.Killer dans le forum C++
    Réponses: 11
    Dernier message: 04/12/2005, 13h42

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