Forum Programmation.c++ Constructeur : mauvais constructeur choisi

Posté par  . Licence CC By‑SA.
Étiquettes : aucune
1
29
sept.
2013

Bonjour,

Je code un programme et le compilateur m'envoie un message bien cryptique.
J'ai une classe MaClasse qui hérite de QObject (en public). Elle contient un pointeur vers un QTcpSocket.
Dans le header de la classe, je n'ai défini qu'un seule constructeur :

class MaClasse : public QObject
{
public:
    MaClasse (QTcpSocket* socket);

private:
    QTcpSocket* m_socket;
};

La définition est très simple:

MaClasse::MaClasse (QTcpSocket* socket) : m_socket (socket)
{
}

Lors de la compilation, j'ai cependant l'erreur cannot convert 'QTcpSocket*' to 'MaClasse*' in initialization
Je ne comprends pas cependant comment cela peut arriver. J'ai bien défini un constructeur pour ce cas précis.

Si l'intelligence collective de la Matrice du forum, pourrait (encore une fois) m'aider je serait bien reconnaissant,
Plume

  • # Masquage d'identifiant

    Posté par  (site web personnel) . Évalué à 2.

    Lors de la compilation, j'ai cependant l'erreur

    Quel est le code qui produit l'erreur? Le constructeur?

    Mon hypothèse est que tu tentes une allocation de type

    QTcpSocket* a;
    MaClasse* b = a;

    qui ne fonctionne pas pour la bonne raison qu'elle ne veut rien dire et que tu n'as pas défini de conversion dans ton exemple (comme tu as l'air de le croire).

    Mais sans ton code qui déclenche l'erreur, c'est impossible d'être catégorique.

    • [^] # Re: Masquage d'identifiant

      Posté par  . Évalué à 1.

      Le code est le suivant:

      //Un QTcpServer* a été déclaré plutôt sous le nom m_server
      QTcpSocket* nouveauSocket = m_server->nextPendingConnection();
      MaClasse* nouvClasse (nouveauSocket);
      //Après on fait différentes choses avec la classe, mais tout est bon a ce niveau

      Après coup j'ai essayé de faire ceci parce l'écriture avec le signe égal m'a fait tilter un peu:

      MaClasse nouvClasse = new MaClasse (nouvSocket);

      Là, le compilateur ne me jette pas de message d'erreur plein le terminal. Est-ce la bonne façon ou juste un gros hack bien moche qui marche juste dans ce cas, je ne sais pas. Cependant, j'ai su faire ajouter un constructeur pour le champ QObject et ça marche au niveau de la compilation.

      • [^] # Re: Masquage d'identifiant

        Posté par  (site web personnel) . Évalué à 5.

        Est-ce la bonne façon ou juste un gros hack bien moche qui marche juste dans ce cas, je ne sais pas.

        Ton programme d'avant est faux, tout simplement.

        MaClasse* nouvClasse (nouveauSocket);

        ne fait pas du tout ce que tu penses: cela initialise un pointeur nouvClasse sur type MaClasse avec la valeur nouveauSocket. En l'absence de surcharge d'opérateurs etc., c'est exactement comme si tu avais écrit

        MaClasse* nouvClasse = nouveauSocket;

        et le message du compilateur devient limpide. En C++ (langage tout pourri™) il y a deux-cent treize façons d'initialiser les variables qui se mélangent avec les initialisations des objets. Tu viens de te faire avoir par un des aspects deagréables du langage qui favorise la confusion entre les variables «immédiates» et les objets (les premières n'ont pas de constructeur).

        Tu peux aussi écrire

        int n (1);

        pour initialiser un entier.

        C'est quoi ton livre pour le C++? Comme apparemment tu débutes dans le langage, je te recommande:

        http://www.parashift.com/c++-faq/
        http://yosefk.com/c++fqa/index.html

        (En anglais.) Cela devrait t'aider à avoir une vision plus claire du langage plus utile qu'une conception basée sur «les gros hacks bien moches».

        Et ta version avec le new est bel et bien la façon idoine de faire.

        Bon courage!

        • [^] # Re: Masquage d'identifiant

          Posté par  . Évalué à 0.

          J'en ai deux :

          • un vieux qui n'est ni très pédagogique ni très soucieux des standards de 2003
          • celui du site du zéro qui est peut-être plus pédagogique, mais explique bien moins comment les choses fonctionnent

          Du coup, je me fais mes exercices moi-même (soit des trucs purement pour l'exercice (calculer des collisions d'atomes à la Newton), soit pour un cas concret comme ici) et quand j'ai un problème je regarde un peu partout.
          Après effectivement, ma démarche n'est pas superbe peut-être, mais j'ai déjà appris plus comme ça que durant les cours de la Fac (les tableaux sont prévu pour la fin de semestre!).

          Merci tout de même pour les liens! J'aime le C++ parce que je trouve qu'il donne un accès naturel à la façon dont doit réagir une machine aux ordres qu'on lui donne. L'argument du langage pourri ne compte pas pour moi. Le jour où j'aurai deux cerveau, je ferais du orienté objet en assembleur :P

          Merci beaucoup encore et j'espère que la prochaine fois que j'écrirais ici sera parce que je voudrai partager du code et non des erreurs de compilations :)

          • [^] # Re: Masquage d'identifiant

            Posté par  (site web personnel) . Évalué à 3.

            Pour un bouquin je te conseille "Apprendre le C++" de Claude Delannoy au édition Eyrolles : http://www.editions-eyrolles.com/Livre/9782212121353/

            C'est un des meilleurs que j'ai trouvé. Une fois ce dernier lu, tu pourras passer au C++ de Bjarne Stroustrup.

            Pour compléter le message de Michaël :

            int* pointer; // créé un pointeur (4 octet dans ta pile) qui pointe vers une zone mémoire qui contient un entier.
            int* pointer(12345678); // créé un pointeur vers un entier qui pointe vers l'adresse 12345678 de zone mémoire.
            int* pointer = 12345678; // créé un pointeur vers un entier (initialisé à l'addresse 0) et *ensuite* change la valeur du pointeur pour l'adresse 12345678;
            MaClass* pointer; // un pointer vers un zone mémoire qui contient un objet de type MaClass. (L'objet en question n'est pas créé)
            MaClass* pointer(new MaClass(socket)); // créé un objet dans le tas de type MaClass et l'initialise avec le constructeur qui prend en entré un pointer vers un QTcpSocket. *Ensuite* il créé un pointeur dans la pile et l'initialise avec l'adresse de l'objet créé (retourné par new)
            MaClass* pointer(socket); // créé un pointeur qui doit pointer vers un objet de type MaClass et l'initialise avec l'adresse d'une zone mémoire qui contient un QTcpSocket (D'où l'erreur)

            Matthieu Gautier|irc:starmad

        • [^] # Re: Masquage d'identifiant

          Posté par  . Évalué à 1.

          En C++ (langage tout pourri™) il y a deux-cent treize façons d'initialiser les variables

          en fait, pour la deuxieme syntaxe (celle qui n'est pas triviale)
          il suffit de penser à l'initialisation des données membre dans les constructeurs :

          maclasse::maclasse(int a) : m_a(a)
          {
          }

          on a donc : m_a(a); qui corresponds a m_a=a;
          donc ca ne fait pas excatement 213, mais une fois qu'on a compris ca va mieux.

          • [^] # Re: Masquage d'identifiant

            Posté par  (site web personnel) . Évalué à 0.

            on a donc : m_a(a); qui corresponds a m_a=a;

            Comme je l'ai écrit, c'est la syntaxe d'initialisation de type constructeur. Ceci a deux inconvénients car:

            • les entiers ne sont pas des objets donc la notation pousse à confusion;

            • les initialisations par = n'ont pas été abandonnées.

            Cela contribue au fait que C++ est un langage tout pourri™.

            donc ca ne fait pas excatement 213,

            Il y en a plus que deux ce qui fait déjà largement plus que dans la plupart des langages.

            mais une fois qu'on a compris ca va mieux

            C'est quoi que je n'ai pas compris d'après toi?

            • [^] # Re: Masquage d'identifiant

              Posté par  . Évalué à 3.

              ne soit pas agressif,
              j'ai voulu donner une astuce, un moyen memotechnique pour expliquer d'ou vient cette notation qui n'est pas trivial.

              Ne prends pas ça pour toi, quand tu sera calmé tu pourra relire, tu vera il n'y a pas d'agression de ma part.

              • [^] # Re: Masquage d'identifiant

                Posté par  (site web personnel) . Évalué à 1.

                ne soit pas agressif,

                Je ne suis pas agressif. (?)

                j'ai voulu donner une astuce, un moyen memotechnique pour expliquer d'ou vient cette notation qui n'est pas trivial.

                C'est gentil mais trouver «un moyen memotechnique pour expliquer d'ou vient cette notation qui n'est pas trivial» n'a pas grand chose à voir avec la choucroute.

                Le problème est que des notations d'apparence similaire sont utilisées pour des choses différentes (initialisationde variable immédiate dans un cas, initialisation d'objet dans l'autre) ce qui du coup induit le programmeur en erreur. (Ici il confond le pointeur et l'objet pointé, et le compilateur analyse l'erreur d'une autre façon, ce qui aboutit à un message d'erreur pas utile.)

                Ne prends pas ça pour toi, quand tu sera calmé tu pourra relire, tu vera il n'y a pas d'agression de ma part.

                Pas de problème, la prochaine fois que quelqu'un fera un commentaire hors sujet qui se termine par «une fois qu'on a compris ça va mieux» je lui enverrai une carte postale avec des petits chatons. :)

                • [^] # Re: Masquage d'identifiant

                  Posté par  . Évalué à 3.

                  Bon, je vais expliquer.
                  Désolé de te le dire, mais tout ne tourne pas autour de ta petite personne, tu as l'impression que mon post "à coté de la choucroute" parceque tu ne comprends pas que je ne te reponds pas directement, j'utilise ton poste pour completer, pour donner une information supplementaire.

                  Regardons les choses simplement : l'auteur original, n'est vraiment pas un expert en C++, toi de toute evidence tu t'y connais tres bien, (et même surement plus que moi, sans aucun doute).
                  tu lui fait une reponse tout a fait exacte, dans laquel tu donne la fameuse syntaxe d'initialisation suivante : "int n (1);"
                  Bon et en gros, il est question du fait que le C++ est pourrit et qu'il y a 213 maniere d'instancier. (bien sur que je ne t'ai pas pris au mot)

                  Moi, on intention était simplement de donner une expication supplementaire qui n'est pas explicitement livré dans ton post, j'ai essayé de me mettre à son niveau en faisant une analogie directe entre :
                  - l'intitialisation d'une donnée membre d'une classe "maclasse::maclasse(int a) : m_a(a)"
                  - et la syntaxe "m_a(a);"

                  Oui je sais pour toi c'est trivial, tu as sans doute l'impression que ca ne sert a rien de le préciser.

                  J'en ai profité pour décomplexer un peu l'utilisateur en lui disant que ca ne fait peut être pas exactement 213 (car de toute maniere je n'ai pas compté combien il y en a, peu importe) et que c'est plus simple quand on a compris…et là bien sur je ne parle pas de toi, (t'es un peu parano?), mais je parle d'avoir compris la similitude entre les 2 cas, et donc quand on a compris que la syntaxe bizard vient en fait de l'initialisation des donnée même lors du constructeur c'est plus simple oui, du coups on sais pourquoi cetet syntaxe existe.

                  Apres chacun sa manière d'expliquer les choses, moi j'apelle ca une astuce, un moyen memotechnique. Tu dois être sacrement intelligent, et bien tu trouve que c'est nul ou a coté de la choucroute, moi c'est pour Plume que ça s'adressait.
                  Le reste je m'en fou un peu, j'ai autre chose a faire dans la vie de checker si un type a repris une de mes phrase dans un forum.

                  Salutations

                  • [^] # Re: Masquage d'identifiant

                    Posté par  (site web personnel) . Évalué à 1.

                    Désolé de te le dire, mais tout ne tourne pas autour de ta petite personne

                    Gnii? De quoi tu parles?

                    parceque tu ne comprends pas que je ne te reponds pas directement, j'utilise ton poste pour completer,

                    C'est quoi les indications que tu as laissées pour comprendre ton message dans ce sens?

                    Le reste je m'en fou un peu, j'ai autre chose a faire dans la vie de checker si un type a repris une de mes phrase dans un forum.

                    C'est pas toi qui en remet 36 couches?

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.