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 :

[debutant] question sur la surcharge des operateurs


Sujet :

C++

  1. #1
    Membre du Club
    Inscrit en
    Décembre 2006
    Messages
    112
    Détails du profil
    Informations forums :
    Inscription : Décembre 2006
    Messages : 112
    Points : 46
    Points
    46
    Par défaut [debutant] question sur la surcharge des operateurs
    slt ma question est tres simple ,comment on fait pour savoir si la fonction qui surcharge un operateur doit etre une methode amie ou pas ?
    Merci bcp

  2. #2
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 381
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 381
    Points : 41 582
    Points
    41 582
    Par défaut
    Je dirais qu'elle a besoin d'être amie seulement si elle utilise des membres non-publics de la classe...

  3. #3
    Membre éprouvé
    Avatar de NiamorH
    Inscrit en
    Juin 2002
    Messages
    1 309
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 1 309
    Points : 1 051
    Points
    1 051
    Par défaut
    Je ne sais pas si la question n'était pas plutôt de savoir comment choisir un opérateur membre ou non membre ?

    Si c'est bien ça ta question, alors saches qu'il est nécessaire de passer par un opérateur non membre lorsque ton objet se trouve en deuxième opérande d'un opérateur binaire.

    Par exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class Test
    {};
     
    Test t;
    int i;
     
    // Opérateur membre ok
    t + i;
     
    // Opérateur non membre obligé
    i + t;

  4. #4
    Membre du Club
    Inscrit en
    Décembre 2006
    Messages
    112
    Détails du profil
    Informations forums :
    Inscription : Décembre 2006
    Messages : 112
    Points : 46
    Points
    46
    Par défaut
    ok merci bcp ,sinon en faisant un exercie j'ai rencontré un truc bizzare voila le 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
     
    tableau::tableau():nbvaleur(1),valeurs(new int)
    {}
    tableau::tableau(int nb):nbvaleur(nb),valeurs(new int[nb])
    {
        for (int i=0;i<nbvaleur;i++)
        {
            valeurs[i]=0;
        }
        }
    tableau::~tableau()
    {
        delete [] valeurs ;
    }
     
    bool tableau::indice(int ind)const
    {
        if (ind>0 && ind<nbvaleur)
        {
            return true;
        }
        throw("indice hors borne\n");
    }
     
    int& tableau::operator[](int ind)const
    {
     
    try
    {
       indice(ind);
    }
        catch(const char* erreur)
        {
            cout<<erreur<<endl;
        }
           return valeurs[ind];
    }
     
     
     
    int main()
    {
        const tableau t(10); // le tableau est declaré comme constant mais je peux //le modifier
     
        cout<<t[1]<<endl;
        t[1]=1; // prq ça fonctionne ?
        cout<<t[1]<<endl;
        cin>>t[1];// de meme ici
        cout<<t[1];
        return 0;
     
    }
    merci

  5. #5
    Membre éprouvé
    Avatar de NiamorH
    Inscrit en
    Juin 2002
    Messages
    1 309
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 1 309
    Points : 1 051
    Points
    1 051
    Par défaut
    Ca fonctionne car l'opérateur [] est déclaré const mais il renvoie aussi une référence non constante vers un des éléments;

    Si tu modifies le retour de l'opérateur [] de int & en int const & cela serait plus logique.

  6. #6
    Membre averti Avatar de Kujara
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    262
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Décembre 2006
    Messages : 262
    Points : 358
    Points
    358
    Par défaut
    Ca marche parceque ton operateur [] renvoie un int &.

    la version correcte prends 2 operateurs [] :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    const int & tableau::operator[](int ind)const
    {
    }
    int& tableau::operator[](int ind)
    {
    }
    L'un est const et renvoie un const int &, l'autre n'est pas const et autorise la modification de l'int renvoyé.

  7. #7
    Membre du Club
    Inscrit en
    Décembre 2006
    Messages
    112
    Détails du profil
    Informations forums :
    Inscription : Décembre 2006
    Messages : 112
    Points : 46
    Points
    46
    Par défaut
    ok merci bcp .

  8. #8
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 282
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 282
    Points : 11 036
    Points
    11 036
    Par défaut
    Citation Envoyé par hunter99 Voir le message
    slt ma question est tres simple ,comment on fait pour savoir si la fonction qui surcharge un operateur doit etre une methode amie ou pas ?
    L'amitié est rarement nécessaire.
    Dans le cas des opérateurs mathématiques, pour raisons de symétries, on rend les opérateurs binaires libres, et par commodité dépendant de ceux auto-modifiant (je ne trouve pas de meilleur nom)
    ->
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    struct T {
        T& operator+=(T const& rhs) { 
            ....
            // opérateur membre => l'amitié ne veut rien dire pour lui
        }
    ...
    };
     
    T operator+(T const& lhs, T const& rhs) {
        return T(lhs) += rhs;
    }
    Cas particulier: quand un opérateur lie deux classes différentes comme un vecteur et une matrice. Même en présence d'accesseurs qui vont bien (operateur[]), il est fréquent d'utiliser l'amitié pour raisons d'optimisation. Dans ce cas là, ce n'est pas choquant vu qu'il s'agit de toutes façons de classes très liées.

    Pour les opérateurs liés aux flux, on peut s'en passer à l'aide de constructeurs d'initialisation (plus un moyen de mettre à jour une tierce donnée de même type (opérateur d'affection, swap, ...)), et des accesseurs qui vont bien.
    Ceci dit, il est fréquent de voir ces opérateurs en amis (avec présence d'un constructeur par défaut).

  9. #9
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Citation Envoyé par Luc Hermitte Voir le message
    Dans le cas des opérateurs mathématiques, pour raisons de symétries, on rend les opérateurs binaires libres, et par commodité dépendant de ceux auto-modifiant (je ne trouve pas de meilleur nom)
    Si tu fais une multiplication de matrices, tu vas avoir tendance a implementer l'auto-modifiant en utilisant la version libre :-)

  10. #10
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 282
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 282
    Points : 11 036
    Points
    11 036
    Par défaut
    (Plus un petit swap qui va bien.)
    Ce pas faux. En effet. J'avais complètement zappé cette famille de cas.

  11. #11
    r0d
    r0d est déconnecté
    Expert éminent

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 266
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 266
    Points : 6 688
    Points
    6 688
    Billets dans le blog
    2
    Par défaut
    Et pour la surcharge des opérateurs d'indirection de flux dans une classe template, vous feriez comment?

    Par exemple, une classe Matrix qui implémente une matrice 2D template du style:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    template <typename T>
    class Matrix
    {
    // constructeurs, opérateurs, ...
     
    private:
        std::vector<T> _matrix;
    };
    . Quelle serait la meilleure solution?

  12. #12
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Citation Envoyé par r0d Voir le message
    Et pour la surcharge des opérateurs d'indirection de flux dans une classe template, vous feriez comment?
    Ils sont d'office externes à la classe et en général les classes ont une interface permettant de les implémenter sans les rendre friend (ou alors on peut se demander si ce n'est pas de l'aide au débuggage plus qu'une fonctionnalité de la classe).

  13. #13
    r0d
    r0d est déconnecté
    Expert éminent

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 266
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 266
    Points : 6 688
    Points
    6 688
    Billets dans le blog
    2
    Par défaut
    Ok merci.

    Du coup, je me demande ce que vous pensez de cette solution:
    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
    59
    60
    61
    62
    63
    #include <vector>
    #include <ostream>
    #include <algorithm>
     
     
    template <typename T>
    class Matrix2D
    {
    public:
    	Matrix2D(unsigned int nbCol = 4, unsigned int nbRow = 4)
    		: _nbCol(nbCol)
    		, _nbRow(nbRow)
    		, _matrix( std::vector<T>(nbCol*nbRow) )
    	{}
     
    	~Matrix2D(){}
     
    	void Fill(T elt)
    	{
    		std::fill(_matrix.begin(), _matrix.end(), elt);
    	}
     
    	struct DumpOne
    	{
    		DumpOne(std::ostream & stream, unsigned int nbCol)
    			: _count(0)
    			, _stream(stream)
    			, _nbCol(nbCol)
    		{}
     
    		void operator () (T& t)
    		{
    			_stream << t;
    			if (++_count==_nbCol)
    			{
    				_stream << std::endl;
    				_count = 0;
    			}
    		}
     
    	private:
    		unsigned int	_count;
    		std::ostream &	_stream;
    		unsigned int	_nbCol;
    	};
     
    	void Dump(std::ostream & stream)
    	{
    		std::for_each( _matrix.begin(), _matrix.end(), DumpOne(stream, _nbCol) );
    		stream << std::endl;
    	}
     
    private:
    	unsigned int _nbCol, _nbRow;
    	std::vector<T> _matrix;
    };
     
    template <typename T>
    std::ostream & operator << (std::ostream & stream, Matrix2D<T> & matrix)
    {
    	matrix.Dump(stream);
    	return stream;
    }

  14. #14
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    for_each est autorise a copier comme il veut l'objet fonction qui lui est passe. Donc le modifier comme tu le fais n'est pas sage -- ca peut marcher avec une implementation et pas avec un autre.

  15. #15
    r0d
    r0d est déconnecté
    Expert éminent

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 266
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 266
    Points : 6 688
    Points
    6 688
    Billets dans le blog
    2
    Par défaut
    Ha. Que devrais-je donc faire pour y remédier? Implémenter le constructeur par copie du foncteur DumpOne ?

  16. #16
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Donner a DumpOne une semantique de reference. Le texte de la future norme suggere pour le moment l'utilisation de reference_wrapper<T>, mais je doute que ce soit une solution pour toi pour le moment.

  17. #17
    r0d
    r0d est déconnecté
    Expert éminent

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 266
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 266
    Points : 6 688
    Points
    6 688
    Billets dans le blog
    2
    Par défaut
    Ok d'ac. M'enfin, c'est par curiosité que je demandais ça, je n'ai pas besoin de ça pour l'instant.

    Tiens, en parlant de la nouvelle norme, tu as vu qu'il y a un meeting prévu à sofia antipolis du 8 au 14 juin 2008? ( cf le blog d'H.S.)

  18. #18
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Citation Envoyé par r0d Voir le message
    Tiens, en parlant de la nouvelle norme, tu as vu qu'il y a un meeting prévu à sofia antipolis du 8 au 14 juin 2008? ( cf le blog d'H.S.)
    Je suis au courant.

Discussions similaires

  1. Réponses: 2
    Dernier message: 22/04/2006, 18h18
  2. question sur le rafraichissement des données dans la base
    Par vbcasimir dans le forum Bases de données
    Réponses: 8
    Dernier message: 06/06/2005, 12h44
  3. question sur le comportement des threads
    Par rose-bonbon dans le forum CORBA
    Réponses: 4
    Dernier message: 27/10/2004, 18h00
  4. question sur le format des images ..
    Par vbcasimir dans le forum Langages de programmation
    Réponses: 7
    Dernier message: 28/08/2003, 12h08
  5. [debutant] Questions sur 1 futur projet
    Par cyrull22 dans le forum XML/XSL et SOAP
    Réponses: 3
    Dernier message: 28/04/2003, 21h49

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