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 :

Constructeurs explicites


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éprouvé
    Inscrit en
    Novembre 2006
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 073
    Par défaut Constructeurs explicites
    Autre question sur l'appel de fonction.
    Il semble qu'il y a des fonctions qui prennent des arguments, mais qui ne sont pas écrits, explicitement dans la liste d'arguments.
    Par exemple, la fonction f2 définie ici:

    http://msdn.microsoft.com/en-us/libr...48(VS.80).aspx

    je la redonne ici:
    C2 est une classe, mais il n'y a pas d'arguments. Que fait une telle fonction?
    Si on veut faire qqch de l'argument de type C2, que fait-on?
    merci

  2. #2
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Dans le cas que tu présente, il est plus que possible que la fonction doive respecter une certaine signature, mais que, exceptionnellement (sans doute parce que c'est une fonction virtuelle), l'argument ne sera pas utilisé.

    Si nous nommions l'argument, le compilateur se plaindrait d'avoir une variable (non de l'argument) définie mais jamais utilisée.

    Si on souhaite pouvoir accéder à l'argument, il faudra lui donner un nom
    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

  3. #3
    Membre éprouvé
    Inscrit en
    Novembre 2006
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 073
    Par défaut
    D'ailleurs, dans le code de la page MSDN, il y a une conversion, que je reproduis ici:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    void g(int i)
    {
        f2(i);   // C2558
        // try the following line instead
        // f2(C2(i));
    }
    Ne faudrait-il pas, pour être en conformité avec le C++, écrire:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     f2(static_cast<C2>(i));
    plutôt que
    Enfin, quand on déclare un constructeur "explicit", et que l'on fait passer un argument par valeur, il y a appel du constructeur par copie.
    Mais je ne comprends pas pourquoi cela provoque une erreur.

    Car si on déclare un objet c (en l'occurence de classe C dans le cas présent)
    et que l'on fait par exemple:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    C  f(C c){   
        c.i = 2;
        return c;   // first call to copy constructor
    }
    int main(){
     
        C c, d;
    d = f(c);    //   c is copied 
    }

    il y aura deux erreurs, l'une pour f(c) l'autre pour return c.
    mais où sera la conversion implicite?
    Merci

  4. #4
    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
    Cela correspond au 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
    #include <iostream>
    class C
    {
    public:
        int i;
        explicit C(const C&)   // an explicit copy constructor
        {
            std::cout<<"\nin the copy constructor";
        }
        explicit C(int i )   // an explicit constructor
        {
            std::cout<<"\nin the constructor";
        }
     
        C()
        {
            i = 0;
        }
    };
     
    class C2
    {
    public:
        int i;
        explicit C2(int i )   // an explicit constructor
        {
        }
    };
     
    C f(C c)
    {   // C2558
        c.i = 2;
        return c;   // first call to copy constructor
    }
     
    void f2(C2)
    {
    }
     
    void g(int i)
    {
        f2(i);   // C2558
        // try the following line instead
        // f2(C2(i));
    }
     
    int main()
    {
        C c, d;
        d = f(c);   // c is copied
     
        return 0;
    }
    L'idée est de mettre en évidence partout où un constructeur était appelé. En le mettant explicit, cela force à appeler explicitement le constructeur et donc prendre conscience où ces appels avaient lieu.

  5. #5
    Membre éprouvé
    Inscrit en
    Novembre 2006
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 073
    Par défaut
    oK, je sais bien. Mais en quoi ce code pose t il un pb au compilateur:
    quand je rentre ce code dans vC2010, j'ai pour erreur;
    class "C" has no suitable copy constructor


    De plus, ai-je raisons quant à ma remarque sur le static_cast?

  6. #6
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Il faudrait voir de quoi est composé C, comment tu essaye de construire un objet de type C, et comment tu essaie de construire tes objets dont le type dérive de C.

    si tu essaye d'invoquer un constructeur de C prenant un paramètre alors qu'il n'existe aucune constructeur acceptant le type de paramètre en question, ou, au contraire, si tu essaye de construire C en ne lui fournissant aucun argument alors qu'il en attend un, fatalement, le compilateur ne pourra jamais déterminer quel constructeur il doit invoquer.

    C'est, en gros, ce que te dis le message d'erreur.

    Ainsi, il est plus que probable que tu aies une classe C proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    class C
    {
        public:
            explicite C(int i);
    };
    et que le constructeur de la classe C2 qui dérive de C n'appelle pas explicitement le constructeur... prenant un entier de C.

    Ou, c'est l'inverse qui se passe: C dispose d'un constructeur "par défaut", mais d'aucun constructeur demandant un entier, et tu essaye d'invoquer un constructeur pour C en lui donnant un entier.

    Et, pour répondre à ta dernière question, tu as tord au niveau du static_cast.

    Il faut comprendre que les static_/dynamic_/reinterpret_ cast provoquent ce que l'on appelle le transtypage.

    Cela revient à faire passer un(e référence ou un pointeur sur un) objet de type X pour un(e référence ou un pointeur sur un) objet Y, en appliquant des "normes de sécurité" variable au moment où on prend la décision.

    Cela implique que tu... dois avoir, effectivement, un objet à transtyper

    Le constructeur, quant à lui, permet de créer un objet "tout beau, tout propre" du type indiqué et d'en définir les membres sur base des informations que l'on transmet (et que l'on a sans doute récupérées par ailleurs).

    Par contre, une fois qu'un objet a été créé (que son constructeur a été appelé), on peut envisager de le transtyper en un autre, pour autant que l'on respecte certaines règles

    Il faut aussi noter que le transtypage n'a rien à voir avec une quelconque conversion...

    La création ou la conversion de type créent réellement une nouvelle variable, alors que le transtypage revient (en y allant, il est vrai, un peu fort) à mentir au compilateur sur le type de l'objet que l'on utilise
    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

  7. #7
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    57
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2005
    Messages : 57
    Par défaut
    Citation Envoyé par 3DArchi Voir le message
    Cela correspond au code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    C f(C c)
    {   // C2558
        c.i = 2;
        return c;   // first call to copy constructor
    }
    ....
     
    d = f(c);   // c is copied
    Attendez. Le 1er commentaire a l'air de dire que c'est a l'instruction return c que le constructeur de copie est appele. Si je ne m'abuse, c'est plutot au passage de parametre (et uniquement la) lors de l'appel suivant non ?

  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,
    La réponse est : les 2 !
    Une construction par copie a lieu lorsque le paramètre est transmis à la fonction. Mais le résultat aussi est retourné par valeur et provoque donc un appel au constructeur par copie.

Discussions similaires

  1. [POO] Constructeur devant être rendu explicite
    Par coyotte507 dans le forum C++
    Réponses: 2
    Dernier message: 12/11/2008, 23h12
  2. Constructeur explicite et tableau
    Par methodman225 dans le forum Collection et Stream
    Réponses: 5
    Dernier message: 04/09/2008, 12h59
  3. appel explicite au constructeur
    Par exhortae dans le forum C++
    Réponses: 17
    Dernier message: 01/03/2008, 16h05
  4. Appel explicite du constructeur de recopie ?
    Par sebkramm dans le forum C++
    Réponses: 6
    Dernier message: 21/11/2007, 10h02

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