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 :

Heritage et problème de constructeur


Sujet :

C++

  1. #1
    Membre régulier
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Février 2013
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Février 2013
    Messages : 8
    Par défaut Heritage et problème de constructeur
    bonjour,
    me revoilà.. ,car je ne vois pas trop d'où cela viens(enfin si mais n'arrive pas a le résoudre) il râle pour le constructeur de ma classe dans la quelle je définie des constante.. puis le destructeur qui quant à lui fait appel au destructeur de la classe mère.. à savoir je suis relativement débutant en c++ enfin voici donc les erreurs de compile :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    r_toto.cpp:9: error: expected unqualified-id before ':' token
    r_toto.cpp:16: error: expected unqualified-id before ':' token
    et voici mes mon point .h :
    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
     
    #ifndef _TOTO_H_
    #define _TOTO_H_
    #include "c_mysql.h"
    #include "mysql_stop.h"
    #include "error.h"
    #include "c_logvar.h"
    #include "c_buffer.h"
     
     
    class Toto: public c_mysql{
            public:
                    Toto();
                    ~Toto();
                    void c_mysql(const char *_HOST,const char *_USER,const char *_PWD,const int _PORT,const char *_SOCKET,const char *_BD,error *_ERR,c_logvar *_CL,const char *);
                    void init_db(); //initialisation de la base
                    void in_mysql_close(const char *);
            };
    #endif
    et ici mon ..cpp

    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
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <iostream>
    #include <mysql.h>
    #include "c_mysql.h"
    #include "r_toto.h"
     
     Toto:Toto(){ //mon constructeur...
     const char *Host ="martin05";
     const char *User ="toto";
     const char *Pwd ="toto";
     const char *Port ="3306";
     const char *Socket;
     }
     Toto:~Toto(){ // destructeur 
     c_mysql::~c_mysql();
     }
     
    void Toto::init_db (){
     
            MYSQL connmysql;
     
            if(mysql_init(&connmysql)==NULL){
                    std::cout<<"erreur d'initialisation\n";
            }else {
                    std::cout<<"initialisation reussi\n";
            }
     
    }
     int main(int argc, char *argv[]){
             Toto to;
             to.init_db();
             return 0;
     }
    une idée, ou piste car moi je ne vois pas trop , et je pense pas qu'il râle pour que je luis mette un void devant.. ou type primitif ?!

  2. #2
    Membre Expert Avatar de Astraya
    Homme Profil pro
    Consommateur de café
    Inscrit en
    Mai 2007
    Messages
    1 048
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Consommateur de café
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2007
    Messages : 1 048
    Par défaut
    Bonjour,

    Le destructeur de c_mysql n'est pas virtuel? si tu en hérites, il serait bon de le mettre virtuel. Si il ne l'ai pas et que ce n'est pas ta classe, il serait bon de ne pas l'hériter mais de composer ta classe Toto avec un objet c_mysql.
    un destructeur ne devrait jamais être appelé de façon explicite.

    PS: pour plus d'information peut-on avoir la déclaration de la classe c_mysql?

  3. #3
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 147
    Billets dans le blog
    4
    Par défaut
    Bonjour,

    le préfixe d'un constructeur ou destructeur, comme toute autre méthode (ou variable) membres est ::

    Donc Toto:Toto entraîne un
    expected unqualified-id before ':' toke
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  4. #4
    Membre régulier
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Février 2013
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Février 2013
    Messages : 8
    Par défaut
    @Bousk: oui j'ai vu par la suite mon erreur Merci!!

    @Astraya: voici la declaration dans c_mysql :
    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
     
     
    /* Initialisation des variable d'acces a la base de donnes */
    c_mysql::c_mysql(const char *_HOST,const char *_USER,const char *_PWD,const int _PORT,const char *_SOCKET,const char *_BD,error *_ERR,c_logvar *_CL,const char *_nameinit) : PTSTR_HOST(_HOST),PTSTR_
    USER(_USER),PTSTR_PWD(_PWD),PTSTR_SOCKET(_SOCKET),PTSTR_BD(_BD),PORT(_PORT),C_ERROR(_ERR),CL(_CL)
    {
       indice_bdinit=CL->initValue(_nameinit,-1,tab_bdinit,sizeof(tab_bdinit),c_logvar::fct_always_yes);
       mysqldb=NULL;
       ts_last_check_bd=0;
    }
    c_mysql::~c_mysql()
    {
       if (CL->getValue(indice_bdinit))
       {
          if (_ptres)
             freeResult();
          in_mysql_close("~c_mysql");
       }
    }
    ce-ci est l erreur du compilateur:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    r_toto.cpp: In constructor 'Toto::Toto()':
    r_toto.cpp:9: error: no matching function for call to 'c_mysql::c_mysql()'
    c_mysql.h:20: note: candidates are: c_mysql::c_mysql(const char*, const char*, const char*, int, const char*, const char*, error*, c_logvar*, const char*)
    c_mysql.h:18: note:                 c_mysql::c_mysql(const c_mysql&)
    r_toto.cpp: In destructor 'Toto::~Toto()':
    r_toto.cpp:17: error: no matching function for call to 'Toto::~Toto()'
    c_mysql.h:21: note: candidates are: c_mysql::~c_mysql()
    pourquoi confond-t-il la classe c_mysql (c_mysql.h:18: note: c_mysql::c_mysql(const c_mysql&)) et le constructeur c_mysql (c_mysql.h:18: note:c_mysql::c_mysql(const c_mysql&))

  5. #5
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 147
    Billets dans le blog
    4
    Par défaut
    Il te faut maintenant apprendre les bases du langage et sa grammaire.
    Ce que tu écris est faux, et sûrement pas ce que tu veux faire.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    Toto::Toto(){ //mon constructeur...
     const char *Host ="martin05";
     const char *User ="toto";
     const char *Pwd ="toto";
     const char *Port ="3306";
     const char *Socket;
     }
    C'est cool, tu déclares 5 chaînes de caractères. Déclarations qui sont aussitot supprimées dès que sortie de leur portée, portée qui se limite aux accolades..
    Déclarations inutiles donc. Et en activant certaines options du compilateur, tu aurais des warning du type "unused variable".

    De même, quand tu dérives, il te faut appeler un constructeur de la classe mère, pour créer la classe mère justement. Appel implicite d'un constructeur par défaut si aucun n'est précisé.
    c_mysql n'ayant aucun constructeur par défaut, il faut explicitement appeler un constructeur en lui passant les bons paramètres.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  6. #6
    Membre régulier
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Février 2013
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Février 2013
    Messages : 8
    Par défaut
    Ouups pas fait attention le constructeur de la classe mère est appelé dans le constructeur de ma classe et les variables sont déclaré exprès pour les passé en paramètre donc voila en entier mon constructeur. Dsl pour l’omission
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    const char *Host ="martin05";
    const char *User ="toto";
    const char *Pwd ="toto";
    const char *Port ="3306";
    const char *Socket;
    const char *BDD ="tata";
    c_mysql::c_mysql(Host,User,Pwd,Port,Socket,BDD,NULL,NULL);

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 641
    Par défaut
    Salut,

    Dites, les gars, y a vraiment rien qui vous échappe

    Bon, allez, je reprend le code, et je vire ce qui fait des interférences :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    class Toto: public c_mysql{
                  void c_mysql(const char *_HOST,const char *_USER,const char *_PWD,<snip>);
    Comme, apparemment, personne ne l'a remarqué, ce n'est pas comme cela que s'utilise l'héritage public .

    L'héritage est une relation EST-UN, c'est à dire que tout objet de ta classe Toto EST-UN objet de type c_mysql auquel tu auras "ajouté quelques trucs personnel".

    Mais rappelons nous l'ordre de création des différents éléments d'une classe ou d'une structure.

    Lorsque l'on crée une classe ou une structure, les différents membres sont construits dans l'ordre de leur déclaration et, s'il y a un héritage, tous les membres de la classe de base seront créés (également dans l'ordre de leur déclaration) avant la classe dérivée.

    NOTA
    1- Si tu as un héritage multiple (et aucun héritage virtuel), les différentes classes de base seront aussi créés dans l'ordre de leur déclaration
    2 - Pour la destruction, c'est tout juste l'inverse: ce sont d'abord les différents membre de la classe "la plus dérivée" qui sont détruit dans l'ordre inverse de leur déclaration, puis les membres de la classe de base, toujours dans l'ordre inverse de leur déclaration et, s'il y a un héritage multiple (mais aucun héritage virtuel), les différentes classes de base sont détruites dans l'ordre inverse de celle dans laquelle l'héritage a été déclaré.

    Peut etre commence tu à voir où se situe le problème

    Tu ne sais pas construire ton objet de type Toto avant d'avoir construit ton objet de type c_mysql.

    Dés lors, il y a deux solutions:
    1. Soit ta classe c_mysql dispose d'un constructeur (passant pour) ne devant pas recevoir d'argument (soit parce qu'il n'en prend aucun, soit parce qu'il ne prend que des arguments pour lesquels on a donné une valeur par défaut) et, dans ce cas, il sera automatiquement appelé avant meme de construire les différents membres de ta classe (et bien avant d'arriver à l'accolade du constructeur ).
    2. Soit tu dois appeler le constructeur de manière explicite parce que tu dois lui fournir un argument.
    Dans le deuxième cas, tu dois appeler le constructeur de c_mysql au travers de la liste d'initialisation du constructeur de ta classe Toto.

    Un code correct ressemblera donc sans doute à quelque chose comme
    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
    class Derivee : public Base
    {
        public:
            Derivee(/* paramètres éventuels */);
            /* tout le reste mais AUCUNE REFERENCE A Base::quelqueCose
             * (hormi les éventuelles fonctions virtuelles que tu veux
             *   réimplémenter)
             */
    };
    Derivee::Derivee(/* paramètres éventuels*/): Base(/* paramètres requis */),
                                                 premierMember(/* params*/), deuxièmeMembre(/*params*/),
                                                 /*... ,*/ membreN(/*params*/)
    {
        /*reste-t-il encore quelque chose à faire ? */
    }
    Seulement, voilà...

    Je présumes que tu voudrais que les informations "Host","User","Pwd" etc ne doivent pas être à chaque fois indiquées quand tu crées ton objet de type Toto, mais que tu voudrais aussi pouvoir les utiliser pour construire la classe de base c_mysql.

    Or, Comme je te l'ai dit, lorsque tu arrives à l'accolade ouvrante du constructeur de Toto (oui, oui, je parle bien de celle qui précède "reste-t-il encore quelque chose à faire?" ), c'est déjà trop tard

    Et comme l'instance de c_mysql sera d'office créé avant tous les membre de Toto, tu crois sans doute être confronté à un problème impossible à résoudre.

    Mais je te rassure: en informatique, il n'y a jamais de problème, il n'y a que des solutions (le tout étant parfois de les trouver) .

    La solution passe ici par l'utilisation du mot clé static.

    Dans le cadre d'une classe ou d'une structure (parce que classes et structures ne diffèrent que par une seule chose en C++: leur visibilité par défaut ), le mot clé static permet d'indiquer un membre (ou une fonction) qui appartient bel et bien à la classe, mais qui ne dépend d'aucune instance de celle-ci.

    Autrement dit, si tu as une classe qui ressemble à
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    class MaClasse
    {
        public:
            void foo();
            static void bar();
    };
    il faut que tu crées une variable de type MaClasse pour pouvoir appeler foo(); mais ce n'est pas nécessaire pour appeler bar() (bien qu'elle puisse, aussi, être appelée depuis la variable en question)

    Il "suffit", pour pouvoir appeler bar, d'indiquer que c'est une fonction qui vient de la classe MaClasse, sous une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    int main()
    {
        MaClasse::bar(); // ca marche
        // MaClasse::foo() n'ira pas
        MaClasse obj;
        obj.foo(); // ca marche
        obj.bar(); // ca marche aussi :D
        return 0;
    }
    Et donc, nous pourrions envisager d'avoir quelque chose comme
    Toto.h
    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
    class Toto : public c_mysql
    {
        public:
            Toto();
        private:
            /* je n'ai aucune envie que les gens n'aillent voir les valeurs que
             * je donne à toutes ces informations "sensibles" :D
             */
            static const std::string host;
            static const std::string user;
            static const std::string pwd;
            static const std::string socket;
            static const std::string bdd;
            static const int port;
    }
    Toto.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #include <Toto.h>
    const std::string Toto::host = "martin05";
    const std::string Toto::user = "toto";
    const std::string Toto::pwd = "toto";
    const std::string Toto::socket = "this one";
    const std::string Toto::bdd="tata";
    const int Toto::port = 3306;
     
    Toto::Toto:c_mysql(host.c_str(),user.c_str(),pwd.c_str(),port,socket.c_str(),NULL,bdd.c_str(), NULL,NULL)
    {}
    Nota Tu remarqueras que j'ai utilisé, de préférence, la classe std::string pour les chaines de caractères.

    Il s'agit d'une classe, fournie par la bibliothèque standard dans l'espace de noms "std" par simple inclusion du fichier d'en-tête <string>, qui est spécialement prévue pour gérer les chaines de caractères, et qui nous permet d'éviter bien des soucis auxquels nous ne manquerions pas d'être confrontés s'il fallait gérer des chaines "C style".

    La fonction c_str() est une fonction qui renvoie un const char * représentant la chaine de caractères sous une forme "C style", et c'est juste ce qu'il nous faut )
    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

Discussions similaires

  1. Problème définition constructeur
    Par bugland dans le forum Langage
    Réponses: 11
    Dernier message: 12/02/2007, 14h34
  2. Problème de constructeur de copie ?
    Par Bestiol dans le forum C++
    Réponses: 6
    Dernier message: 03/11/2006, 11h28
  3. [2.0][C#] Héritage et surchage du constructeur
    Par Worldofdada dans le forum ASP.NET
    Réponses: 5
    Dernier message: 01/11/2006, 20h16
  4. [POO]Probléme de constructeur virtuel surchargé
    Par Laurent Dardenne dans le forum Delphi
    Réponses: 10
    Dernier message: 15/08/2006, 12h19
  5. [C#] DLL, problème de constructeur
    Par gmonta dans le forum C#
    Réponses: 4
    Dernier message: 30/11/2005, 09h43

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