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 :

appel explicite au constructeur


Sujet :

C++

  1. #1
    Membre éclairé
    Inscrit en
    Janvier 2007
    Messages
    293
    Détails du profil
    Informations forums :
    Inscription : Janvier 2007
    Messages : 293
    Par défaut appel explicite au constructeur
    Bonsoir,

    voilà j'essaie d'implementer une classe String, pour débuter je veux juste surdéfinir l'opérateur = afin de pouvoir faire :


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    String str1 ("bb");
    String str2;
     
    str2 = str1;

    J'ai donc pondu le code suivant :

    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
    #include <iostream>
     
    using namespace std;
     
    class String
    {
       private :
     
          char* m_string;
     
       public :
     
          String (char *string = "")
          {
             m_string = new char[strlen (string) + 1];
             strcpy (m_string, string);
          }
     
          ~String ()
          {
             delete m_string, m_string = NULL;
          }
     
          String & operator= (const String &right)
          {
             delete m_string, m_string = NULL;
     
             String (right.m_string);
     
             return *this;
          }
     
          void display ()
          {
             cout << m_string;
          }
    };
     
    int main ()
    {
       String str1;
       String str2 ("Salut jonjon");
     
       str1 = str2;
     
       str1.display ();
     
       return EXIT_SUCCESS;
    }
    dans la fonction operator= j'essaie d'appeler le constructeur de l'objet pour pouvoir changer sa valeur, mais ça ne marche pas.
    j'aimerais éviter de faire

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
          String & operator= (const String &right)
          {
             delete m_string, m_string = NULL;
     
             m_string = new char[strlen (right.m_string) + 1];
             strcpy (m_string, right.m_string);
     
             return *this;
          }
    merci

  2. #2
    Expert confirmé
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 296
    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 296
    Par défaut
    L'idiome du sawp s'applique parfaitement à ce cas.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    String & String::operator=(String const& rhs) {
       String tmp(rhs);
       this->swap(tmp);
       return *this;
    }
    PS: Tu a oublié plein de "const", et c'est delete[] qu'il te faut appeler, pas delete.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  3. #3
    Rédacteur

    Avatar de Davidbrcz
    Homme Profil pro
    Ing Supaéro - Doctorant ONERA
    Inscrit en
    Juin 2006
    Messages
    2 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ing Supaéro - Doctorant ONERA

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 307
    Par défaut
    C'est normal que ca ne marche pas !
    Dans operator= , String (right.m_string) crée un objet temporaire mais tu ne touche aucunement à *this.

    De ce fait, une 1er solution pourrait être :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    String & operator= (const String &right)
          {
             delete m_string, m_string = NULL;
     
             *this = String (right.m_string); // ca va planter ici
     
             return *this;
          }
    Mais ce code va plante car tu as un appel récursif non controlé de operator=

    Il faut donc alors recopier manulement la chaine dans operator= .

    Edit : Ou passer par une fonction swap comme le dit Luc
    "Never use brute force in fighting an exponential." (Andrei Alexandrescu)

    Mes articles dont Conseils divers sur le C++
    Une très bonne doc sur le C++ (en) Why linux is better (fr)

  4. #4
    Membre éclairé
    Inscrit en
    Janvier 2007
    Messages
    293
    Détails du profil
    Informations forums :
    Inscription : Janvier 2007
    Messages : 293
    Par défaut
    Citation Envoyé par Luc Hermitte Voir le message
    L'idiome du sawp s'applique parfaitement à ce cas.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    String & String::operator=(String const& rhs) {
       String tmp(rhs);
       this->swap(tmp);
       return *this;
    }
    PS: Tu a oublié plein de "const", et c'est delete[] qu'il te faut appeler, pas delete.

    Bonsoir,

    désolé mais je ne sais pas ce qu'est l'idiome du swap,

    faut-il que je définisse dans ma classe une fonction

    void swap (const String &str)

    mais franchement je vois pas trop comment faire ?

    Sinon pour les const oui j'en ai oublié (faut dire que je débute en c++), je posterais le code dans un autre topic pour correction afin d'avoir de bonnes habitudes.

    Merci

  5. #5
    Rédacteur

    Avatar de Davidbrcz
    Homme Profil pro
    Ing Supaéro - Doctorant ONERA
    Inscrit en
    Juin 2006
    Messages
    2 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ing Supaéro - Doctorant ONERA

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 307
    "Never use brute force in fighting an exponential." (Andrei Alexandrescu)

    Mes articles dont Conseils divers sur le C++
    Une très bonne doc sur le C++ (en) Why linux is better (fr)

  6. #6
    Membre éclairé
    Inscrit en
    Janvier 2007
    Messages
    293
    Détails du profil
    Informations forums :
    Inscription : Janvier 2007
    Messages : 293
    Par défaut
    Citation Envoyé par Davidbrcz Voir le message

    Bonsoir,

    oauis c'est pas facile cette histoire , je vais laisser en suspend (le temps que j'arrive à la partie des exceptions) pour pouvoir comprendre tout ça. En attendant j'applique la 2ème solution qui est plus simple.

    Sinon une dernière chose

    je sais que

    const int *p c'est pas la même chose que int * const p

    mais est_ce que const String &right c'est la même chose que String const &right


    Merci

  7. #7
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par exhortae Voir le message
    Je sais que

    const int *p c'est pas la même chose que int * const p

    mais est_ce que const String &right c'est la même chose que String const &right
    Oui. De même que const int* p est la même chose que int const* p.

  8. #8
    Membre éclairé
    Inscrit en
    Janvier 2007
    Messages
    293
    Détails du profil
    Informations forums :
    Inscription : Janvier 2007
    Messages : 293
    Par défaut
    Citation Envoyé par Jean-Marc.Bourguet Voir le message
    Oui. De même que const int* p est la même chose que int const* p.

    Ok merci


    bon je met résolu le temps de voir les exceptions et de rouvrir le fil

  9. #9
    Expert confirmé

    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    4 253
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Février 2007
    Messages : 4 253
    Billets dans le blog
    3
    Par défaut
    Citation Envoyé par exhortae Voir le message
    const int *p c'est pas la même chose que int * const p

    mais est_ce que const String &right c'est la même chose que String const &right
    En fait, pour savoir, il suffit de parenthéser les éléments deux à deux en partant de la gauche:

    String const & right => ((String const) & ) right
    right est donc de type ((String const) &) qui est une référence sur (String const) qui est un String constant.

    const String & right => ((const String) & ) right
    right est donc de type ((const String) &) qui est une référence sur (const String) qui est un String constant (const T et T const sont similaires).

    int * const p => ((int *) const) p
    p est donc de type ((int *) const) qui est une valeur constante de pointeur sur int (donc un pointeur constant).

    const int * p => ((const int) *) p
    p est donc de type ((const int) *) soit un pointeur sur un entier constant

  10. #10
    Membre chevronné
    Profil pro
    Inscrit en
    Février 2008
    Messages
    439
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 439
    Par défaut
    Citation Envoyé par nicroman Voir le message
    En fait, pour savoir, il suffit de parenthéser les éléments deux à deux en partant de la gauche:
    int a[2];
    ->
    (int a) [2]

    vector<int (*) (int)> v;
    ->
    (int (*)) (int)

    ça ne marche que pour * et & qui sont préfixés!

  11. #11
    Membre confirmé Avatar de babar63
    Homme Profil pro
    Développeur jeux vidéos/3d Temps réel
    Inscrit en
    Septembre 2005
    Messages
    241
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France

    Informations professionnelles :
    Activité : Développeur jeux vidéos/3d Temps réel

    Informations forums :
    Inscription : Septembre 2005
    Messages : 241
    Par défaut
    ça ne marche que pour * et & qui sont préfixés!
    Je suppose qu'il parlait simplement d'une méthode pour trouver à quoi const est attaché dans ce cas ça marche bien :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    (const int) a[2];
    (int const) a[2];
    voire même pour :
    (int a) [2];
    Même si le code ne compile on peut parfois se représenter plus facilement ce que cela signifie avec les parenthèse... non?
    Sinon une question
    int (*) (int)
    Je n'ai jamais vu cette notation auparavant... qu'est-ce que cela représente?

  12. #12
    Rédacteur

    Avatar de Davidbrcz
    Homme Profil pro
    Ing Supaéro - Doctorant ONERA
    Inscrit en
    Juin 2006
    Messages
    2 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ing Supaéro - Doctorant ONERA

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 307
    Par défaut
    Un Pointeur de foncion, cette fonction recevant un int en paramètre et en retourne un autre.
    "Never use brute force in fighting an exponential." (Andrei Alexandrescu)

    Mes articles dont Conseils divers sur le C++
    Une très bonne doc sur le C++ (en) Why linux is better (fr)

  13. #13
    Membre éclairé
    Inscrit en
    Janvier 2007
    Messages
    293
    Détails du profil
    Informations forums :
    Inscription : Janvier 2007
    Messages : 293
    Par défaut
    Citation Envoyé par nicroman Voir le message
    En fait, pour savoir, il suffit de parenthéser les éléments deux à deux en partant de la gauche:

    String const & right => ((String const) & ) right
    right est donc de type ((String const) &) qui est une référence sur (String const) qui est un String constant.

    const String & right => ((const String) & ) right
    right est donc de type ((const String) &) qui est une référence sur (const String) qui est un String constant (const T et T const sont similaires).

    int * const p => ((int *) const) p
    p est donc de type ((int *) const) qui est une valeur constante de pointeur sur int (donc un pointeur constant).

    const int * p => ((const int) *) p
    p est donc de type ((const int) *) soit un pointeur sur un entier constant
    eh eh pas mal cette méthode, jvais l'utiliser pour débuter.

    Merci

  14. #14
    Membre chevronné
    Profil pro
    Inscrit en
    Février 2008
    Messages
    439
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 439
    Par défaut
    Citation Envoyé par babar63 Voir le message
    Je suppose qu'il parlait simplement d'une méthode pour trouver à quoi const est attaché dans ce cas ça marche bien :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    (const int) a[2];
    (int const) a[2];
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    const volatile int *p;
    ->
    (((const volatile) int) *)
    ça marche plus!

  15. #15
    Membre confirmé Avatar de babar63
    Homme Profil pro
    Développeur jeux vidéos/3d Temps réel
    Inscrit en
    Septembre 2005
    Messages
    241
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France

    Informations professionnelles :
    Activité : Développeur jeux vidéos/3d Temps réel

    Informations forums :
    Inscription : Septembre 2005
    Messages : 241
    Par défaut
    Je ne connais pas "volatile", mis à part un petit article que je viens de lire en vitesse
    Donc même si je ne peux conseiller cette notation, ce qui est sûr c'est que ca m'aurait personnellement évité de confondre l'utilisation des "const" pendant un bon moment .

  16. #16
    Membre chevronné
    Profil pro
    Inscrit en
    Février 2008
    Messages
    439
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 439
    Par défaut volatile
    Citation Envoyé par babar63 Voir le message
    Je ne connais pas "volatile", mis à part un petit article que je viens de lire en vitesse
    volatile s'utilise :
    • avec setjmp : en C seulement, inutilisable en C++ (interaction avec les destructeurs non définie)
    • pour communiquer entre les gestionnaires de signaux et le code normal. Les gestionnaires de signaux ont une sémantique dépendante du système, et dans le gestionnaire l'utilisation d'appels systèmes est obligatoire (impossible d'utiliser la bibliothèque standard).
    • dans les drivers matériels : pour accéder aux registres "mappés" en mémoires (et encore, volatile ne permet pas toujours cela)
    • pour s'assurer que des accès mémoire ne sont pas supprimés par les optimisations du compilateur, par exemple pour un benchmark (il est difficile d'écrire des benchmark réellement effectifs en présence d'optimisations)

    Il y a assez peu de problèmes pour lesquels volatile est une réponse appropriée. Le plus souvent, quand un programmeur "non confirmé" veut utiliser volatile, c'est qu'il se trompe sur la signification de volatile.

  17. #17
    Membre confirmé Avatar de babar63
    Homme Profil pro
    Développeur jeux vidéos/3d Temps réel
    Inscrit en
    Septembre 2005
    Messages
    241
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France

    Informations professionnelles :
    Activité : Développeur jeux vidéos/3d Temps réel

    Informations forums :
    Inscription : Septembre 2005
    Messages : 241
    Par défaut
    Merci pour l'info, je pense pas en avoir besoin avant un moment alors
    Si toutefois dès personnes sont intéressées voila le site à partir duquel j'ai accédé l'article : http://www.massey.ac.nz/~mgwalker/mi.../volatile.html

  18. #18
    Membre chevronné
    Profil pro
    Inscrit en
    Février 2008
    Messages
    439
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 439
    Par défaut volatile n'est pas pour le multithread
    Citation Envoyé par babar63 Voir le message
    Merci pour l'info, je pense pas en avoir besoin avant un moment alors
    Si toutefois dès personnes sont intéressées voila le site à partir duquel j'ai accédé l'article : http://www.massey.ac.nz/~mgwalker/mi.../volatile.html
    Hum...

    Déjà, Introduction to the Volatile Keyword commence par une description incomplète :
    Citation Envoyé par Introduction to the Volatile Keyword
    In practice, only three types of variables could change:
    • Memory-mapped peripheral registers
    • Global variables modified by an interrupt service routine
    • Global variables within a multi-threaded application
    L'auteur oublie le cas de setjmp (il parle de "C/C++", et du "C keyword volatile", donc setjmp est pertinent).

    Par le suite, on lit :
    Citation Envoyé par Introduction to the Volatile Keyword
    Multi-threaded applications
    [...] another task modifying a shared global is conceptually identical to the problem of interrupt service routines discussed previously. So all shared global variables should be declared volatile.
    Le site est "Embedded.com", et l'article commence par
    Have you experienced any of the following in your C/C++ embedded code?
    cependant beaucoup de programmeurs sur PC ne vont pas prêter attention à ça et vont penser que l'article parle des threads en général.

    Hors, si l'usage de volatile a des chances de suffire sur un système embarqué, probablement pas symétriquement multi-processeurs, volatile ne donne pas au programmeur les garanties nécessaires sur un ordinateur multi-processeurs, multi-core (ce qui revient au même) ou HyperThread. L'article ne mentionne cela à aucun moment!

    Dans Bruce Eckel's Thinking in C++, 2nd Ed, qui à priori ne parle pas spécialement de programmation embarquée, cette section :
    Citation Envoyé par Section 'Specifying storage allocation', sous-section 'volatile'
    If you’re watching a particular flag that is modified by another thread or process, that flag should be volatile so the compiler doesn’t make the assumption that it can optimize away multiple reads of the flag.

    et :
    Citation Envoyé par Section 'volatile'
    Somehow, the environment is changing the data (possibly through multitasking, multithreading or interrupts), and volatile tells the compiler not to make any assumptions about that data, especially during optimization.
    volatile ne doit pas être utilisé à la place des primitives de synchronisation multi-taches (mutex, conditions, sémaphores, rwlock, évènements, barrières...) ni des opérations atomiques (compteur atomique, compare-échange...) qui elles ont un comportement multi-tache bien défini.

    En résumé :
    En règle générale, volatile n'a pas un comportement multi-tache bien défini.

    Si des références disent ou laisse entendre le contraire, c'est mal barré pour apprendre aux gens à programmer correctement.

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

Discussions similaires

  1. Appel explicite du constructeur de recopie ?
    Par sebkramm dans le forum C++
    Réponses: 6
    Dernier message: 21/11/2007, 10h02
  2. Réponses: 12
    Dernier message: 13/10/2007, 11h37
  3. Appel d'un constructeur à partir d'un autre
    Par Pragmateek dans le forum Langage
    Réponses: 28
    Dernier message: 18/06/2006, 01h07
  4. Réponses: 5
    Dernier message: 29/04/2006, 21h41
  5. Appel recursif au constructeur
    Par Math75 dans le forum C++
    Réponses: 1
    Dernier message: 11/10/2005, 15h48

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