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

Langage C++ Discussion :

Assignation implicite : besoin d'explication


Sujet :

Langage C++

  1. #1
    Membre Expert
    Homme Profil pro
    Chercheur
    Inscrit en
    Mars 2010
    Messages
    1 218
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Chercheur

    Informations forums :
    Inscription : Mars 2010
    Messages : 1 218
    Par défaut Assignation implicite : besoin d'explication
    Bonjour,

    j'ai fait une classe générique Number<T> pour avoir mes propres objets Double, Float, Integer, etc :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    template<typename T>
    class Number<T>
    {
        private:
            T _real;
        public:
            Number(T const&);
            Number(Number<T>const&);
            Number<T>& operator=(Number<T>const&);
    };
    L'attribut _real permet de stocker la valeur du nombre. J'ai une question à propose de ce bout de code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    Number<double> a = 1.0;
    a = 2.0;
    A la première ligne, il y a un appel implicite au premier constructeur de ma classe : je n'ai pas de problème avec ça. Par contre, je ne comprends pas pourquoi la seconde ligne fonctionne. Elle est importante car elle me permet ensuite de surcharger les opérateurs "+,-,*,/" de manière efficace (je suis aussi rapide que les opérations classiques en exploitant le tag -O3 de g++).

    Voilà, si quelqu'un pourrait m'éclairer sur ce point et me dire si ce comportement est dans la norme ou si c'est propre à g++.

    Merci

  2. #2
    Membre expérimenté
    Profil pro
    Inscrit en
    Mars 2010
    Messages
    188
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 188
    Par défaut
    tu as un appelle implicite a ton premier constructeur afin de créer un Number<double>const depuis le double 2.0.

    tu peux mettre des logs dans tes constructeurs pour voir ce qui ce passe:
    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
     
    template<typename T>
    class Number
    {
    private:
        T _real;
    public:
        Number(T const& n){
    	std::cout << "constructeur de base avec n = " << n << std::endl;
    	_real = n;
        }
     
        Number(Number<T>const& other){
    	std::cout << "constructeur de recopie avec other._real = " << other._real << std::endl;
    	_real = other._real;
        }
     
        Number<T>& operator=(Number<T>const&other){
    	std::cout << "op affect avec other._real = " << other._real << std::endl;
    	_real = other._real;
        }
    };
     
    int main(int argc, char* argv[])
    {
        Number<double> a = 1.0;
        a = 2.0;
     
        return 0;
    }
    ce qui donne
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    constructeur de base avec n = 1
    constructeur de base avec n = 2
    operateur d'affectation avec other._real = 2

  3. #3
    Membre Expert
    Homme Profil pro
    Chercheur
    Inscrit en
    Mars 2010
    Messages
    1 218
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Chercheur

    Informations forums :
    Inscription : Mars 2010
    Messages : 1 218
    Par défaut
    Bonjour,

    merci pour ta réponse atttchoum.
    Je vais vérifier.

  4. #4
    Membre Expert
    Homme Profil pro
    Chercheur
    Inscrit en
    Mars 2010
    Messages
    1 218
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Chercheur

    Informations forums :
    Inscription : Mars 2010
    Messages : 1 218
    Par défaut
    Merci atttchoum c'était effectivement ce qui se passait!

  5. #5
    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
    Salut,
    Dans ce cas, c'est l'objectif recherché, mais sinon tu as explicit qui permet d'éviter ces conversions implicites :explicit Number(T const&) qui génère ensuite une erreur lors des affectations.
    Ceci dit, j'ai un peu tendance à me méfier des conversions implicites et préfère rajouter une fonction spécifique lorsque j'en ai besoin :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    template<typename T>
    class Number<T>
    {
        private:
            T _real;
        public:
            explicit Number(T const&);
     
            Number<T>& operator=(Number<T>const&);
            Number<T>& operator=(T);
    };
    Enfin, je ne vois pas l'intérêt d'un opérateur d'affectation (Quand dois-je définir l'opérateur d'affectation ?) et d'un constructeur de copie (Quand dois-je définir un constructeur par copie ?) qui font ce que fait celui que fait par défaut le compilateur.

  6. #6
    Membre Expert
    Homme Profil pro
    Chercheur
    Inscrit en
    Mars 2010
    Messages
    1 218
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Chercheur

    Informations forums :
    Inscription : Mars 2010
    Messages : 1 218
    Par défaut
    Bonjour 3DArchi,

    j'ai découvert le mot-clé explicit depuis peu en regardant la manière dont est implémenté Blitz++. Si ma mémoire est bonne, en testant le mot-clé explicit dans l'exemple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    Number<double> a(1.0);
    a = 2.0;
    l'appel au constructeur explicit Number<double>(double const &) est malgré tout effectué. Je vais vérifié pour être sûr.

    Comme tu le suggères, j'ai moi aussi préféré la surcharge
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Number<T> operator=(T const&);
    plutôt que de laisser un appel implicite à un constructeur. J'ai pensé que l'opération serait plus rapide ainsi, peut-être à tort.

    Si je lis correctement
    Enfin, je ne vois pas l'intérêt d'un opérateur d'affectation (Quand dois-je définir l'opérateur d'affectation ?) et d'un constructeur de copie (Quand dois-je définir un constructeur par copie ?) qui font ce que fait celui que fait par défaut le compilateur.
    tu écris que ma classe pourrait simplement s'écrire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    template<typename T>
    class Number<T>
    {
    private:
        T _real;
    public:
        Number(T const&);
        Number<T> operator=(T const&);
    };
    et que je pourrais tout de même écrire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    Number<double> a = 1.0;
    Number<double> b = 2.0;
    a = b;
    Est-ce bien cela? Dans ce cas, si une autre classe hérite de Number<double>, pourrais-je quand même appelé les constructeurs appelés par défaut par le compilateur? Par exemple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    #include "Number.hpp"
    class AnotherClass : private Number<double>
    {
    private:
        // ... des attributs ...
    public:
        AnotherClass(AnotherClass const&);
        // .... des méthodes ...
    }
    et
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    AnotherClass::AnotherClass(AnotherClass const& param)
    :Number<double>(param)
    {
        ;
    }

  7. #7
    Membre Expert
    Avatar de Goten
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Âge : 35
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 580
    Par défaut
    Est-ce bien cela? Dans ce cas, si une autre classe hérite de Number<double>, pourrais-je quand même appelé les constructeurs appelés par défaut par le compilateur? Par exemple
    Oui et oui. Tant que c'est trivial à géré le compilateur le fait très bien. (ie pour le ctor de copie il appel les ctor de copie de tout les membres).

  8. #8
    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
    Salut,
    Citation Envoyé par Aleph69 Voir le message
    Est-ce bien cela? Dans ce cas, si une autre classe hérite de Number<double>, pourrais-je quand même appelé les constructeurs appelés par défaut par le compilateur?
    Oui. Idem pour le destructeur (s'il ne fait rien, laisse le compilateur le définir). Sauf si tu veux en changer une des propriétés (par exemple, rendre le destructeur virtuelle ou protégé pour l'héritage).
    Ceci dit, la classe number a probablement une sémantique de valeur ce qui s'articule mal avec l'héritage.
    Enfin, héritage et sémantique de copie sont souvent incompatibles. Ce qui signifie que si ta classe sert de base à un héritage, il est probable que le constructeur par copie et l'opérateur d'affectation seront supprimés (Comment rendre une classe non copiable).

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. besoin d'explication sur le c++
    Par poporiding dans le forum MFC
    Réponses: 13
    Dernier message: 17/12/2005, 18h01
  2. Besoin d'explications sur un bout de code
    Par zizitop dans le forum C
    Réponses: 7
    Dernier message: 26/04/2005, 14h51
  3. [C#] J'aurais besoin d'explication
    Par Roach- dans le forum Windows Forms
    Réponses: 18
    Dernier message: 10/03/2005, 16h00
  4. Besoin d'explications sur float et l'élasticité !
    Par KneXtasY dans le forum Mise en page CSS
    Réponses: 2
    Dernier message: 14/01/2005, 15h15
  5. [Foreign Key] Besoin d'explication.
    Par Andry dans le forum Débuter
    Réponses: 4
    Dernier message: 28/05/2003, 11h34

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