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 :

[POO] Classe vs constructeur indéfini


Sujet :

C++

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    74
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Octobre 2006
    Messages : 74
    Points : 52
    Points
    52
    Par défaut [POO] Classe vs constructeur indéfini
    Bonjour à tous,

    j'ai un code qui lors de la compilation retourne une erreur "Undefined reference to 'FichierBalises::FichierBalises(char*)'


    voici le code de ma fonction main...
    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
     
    int main(int argc, char *argv[])
    {
        char * nomFicIn;
        try {
            if (argc > 2)
                throw (runtime_error("Trop d'argument spécifiés!"));
            nomFicIn = argv[1];
            FichierBalises unFichier(argv[1]);
        }
        catch (runtime_error erreur) {
            cerr << "Erreur de runtime: " << erreur.what();
            return -1;
        }
        catch (domain_error erreur) {
            cerr << "Erreur de domaine: " << erreur.what();
            return -2;
        }
    }
    et le code de FichiersBalise.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
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
     
    #include <fstream>
    #include <stdexcept>
    #include "balise.hpp"
    using namespace std;
    class FichierBalises{
        public:
        /* FichierBalises
     Ouvre un fichier texte qui sera interprete comme un fichier de balises.
     Lève une exception de type runtime_error en cas d'impossibilité d'ouvrir le fichier
        */
        FichierBalises(char * nomFichier)
        {
            string ligneLue;
            fichier.open(nomFichier);
            if (!fichier)
                throw runtime_error("Le fichier d'entrée est inexistant!");
            this->position = 0;
            while (getline(fichier,ligneLue))
                this->leFichier += ligneLue;
        }
        FichierBalises()
        {
        }
        /* fichierBalisesFerme :
     Ferme un fichier prealablement ouvert par fichierBalisesOuvre
        */
        ~FichierBalises()
        {
            fichier.close();
        }
        /* litProchaineBalise :
        Renvoie la prochaine balise présente dans le fichier non encore retournée par litProchaineBalise.
        Saute par-dessus d'éventuelles zones textuelles le cas échéant.
        Lève une exception de type range_error lorsqu'on atteint la fin du fichier (avant qu'une balise n'ait commencé à être spécifiée)
                (par exemple dans le cas d'un fichier se terminant par <TOTO attr1="toto">)
        Lève une exception de type runtime_error lorsqu'on atteint la fin du fichier alors qu'une balise était en cours de lecture
            (par exemple dans le cas d'un fichier se terminant par <TOTO attr1="toto")
        */
        Balise litProchaineBalise()
        {
            string uneBalise = "";
            while (leFichier[position] != '<' && position < leFichier.length())
                position++;
            if (position < leFichier.length())
                do {
                    position++;
                    if (leFichier[position] == '<')
                        throw runtime_error("Caratère d'ouverture de balise à l'intérieur d'une balise!");
                    uneBalise += leFichier[position];
                } while (leFichier[position] != '>' && position < leFichier.length());
            return (Balise(uneBalise));
        }
        private :
            ifstream fichier;
            string leFichier;
            int position;
    };
    je suis un petit peu perdu pour le moment, j'ai essayé plusieurs façon d'affecter ma classes... mais tous semble générer des erreurs


    Merci à tous

  2. #2
    Membre expert
    Avatar de Klaim
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2004
    Messages
    1 717
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 717
    Points : 3 344
    Points
    3 344
    Par défaut
    A priori je ne vois pas le problème.


    Rectification : a priorio il y a un problème d'inclusion.

    Ta classe FichierBalises doit être déclarée dans un header (par exemple FichierBalises.h) puis potentiellement ses méthodes doivent être définies dans un .cpp (ce qu'on appelle unité de compilation, c'est ce fichier additionné de tous ses includes qui représente le code compilé).
    Ensuite, ton fichier où se trouve le code du main() (main.cpp?) doit inclure le header où se trouve la déclaration de la classe FichierBalises.

    Autrement dit tu devrais avoir quelque chose comme ça :

    FichierBalises.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
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
     
    #ifndef FICHIER_BALISES_H
    #define FICHIER_BALISES_H
     
    #include <fstream>
    #include <string>
    #include "balise.hpp" 
     
     
    class FichierBalises{
        public:
        /* FichierBalises
     Ouvre un fichier texte qui sera interprete comme un fichier de balises.
     Lève une exception de type runtime_error en cas d'impossibilité d'ouvrir le fichier
        */
        FichierBalises(char * nomFichier);
        FichierBalises();
     
        /* fichierBalisesFerme :
     Ferme un fichier prealablement ouvert par fichierBalisesOuvre
        */
        ~FichierBalises();
     
        /* litProchaineBalise :
        Renvoie la prochaine balise présente dans le fichier non encore retournée par litProchaineBalise.
        Saute par-dessus d'éventuelles zones textuelles le cas échéant.
        Lève une exception de type range_error lorsqu'on atteint la fin du fichier (avant qu'une balise n'ait commencé à être spécifiée)
                (par exemple dans le cas d'un fichier se terminant par <TOTO attr1="toto">)
        Lève une exception de type runtime_error lorsqu'on atteint la fin du fichier alors qu'une balise était en cours de lecture
            (par exemple dans le cas d'un fichier se terminant par <TOTO attr1="toto")
        */
        Balise litProchaineBalise();
     
        private :
            ifstream fichier;
            string leFichier;
            int position;
    };
     
    #endif
    FichierBalises.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
    36
    37
    38
    39
    40
    41
    42
    43
    44
     
     
    #include "FichierBalises.h"
     
    using namespace std;
     
    FichierBalises::FichierBalises(char * nomFichier)
        {
            string ligneLue;
            fichier.open(nomFichier);
            if (!fichier)
                throw runtime_error("Le fichier d'entrée est inexistant!");
            this->position = 0;
            while (getline(fichier,ligneLue))
                this->leFichier += ligneLue;
        }
    FichierBalises::FichierBalises()
        {
        }
     
    FichierBalises::~FichierBalises()
        {
            fichier.close();
        }
     
        Balise FichierBalises::litProchaineBalise()
        {
            string uneBalise = "";
            while (leFichier[position] != '<' && position < leFichier.length())
                position++;
            if (position < leFichier.length())
                do {
                    position++;
                    if (leFichier[position] == '<')
                        throw runtime_error("Caratère d'ouverture de balise à l'intérieur d'une balise!");
                    uneBalise += leFichier[position];
                } while (leFichier[position] != '>' && position < leFichier.length());
            return (Balise(uneBalise));
        }
        private :
            ifstream fichier;
            string leFichier;
            int position;
    };
    Et enfin le main.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
     
     
    #include "FichierBalises.h"
     
    int main(int argc, char *argv[])
    {
        char * nomFicIn;
        try {
            if (argc > 2)
                throw (runtime_error("Trop d'argument spécifiés!"));
            nomFicIn = argv[1];
            FichierBalises unFichier(argv[1]);
        }
        catch (runtime_error erreur) {
            cerr << "Erreur de runtime: " << erreur.what();
            return -1;
        }
        catch (domain_error erreur) {
            cerr << "Erreur de domaine: " << erreur.what();
            return -2;
        }
    }


    La variante serait d'avoir tout le code de FichierBalises uniquement dans le header (et donc avec le code "copié" pour chaque cpp qui inclus le header...déconseillé sauf pour les templates et certaines classes triviales).

    FichierBalises.h (avec tout le code dans le header ) :
    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
    54
    55
    56
    57
    58
    59
    60
    61
    62
     
    #ifndef FICHIER_BALISES_H
    #define FICHIER_BALISES_H
     
    #include <fstream>
    #include <stdexcept>
    #include "balise.hpp"
    using namespace std;
    class FichierBalises{
        public:
        /* FichierBalises
     Ouvre un fichier texte qui sera interprete comme un fichier de balises.
     Lève une exception de type runtime_error en cas d'impossibilité d'ouvrir le fichier
        */
        FichierBalises(char * nomFichier)
        {
            string ligneLue;
            fichier.open(nomFichier);
            if (!fichier)
                throw runtime_error("Le fichier d'entrée est inexistant!");
            this->position = 0;
            while (getline(fichier,ligneLue))
                this->leFichier += ligneLue;
        }
        FichierBalises()
        {
        }
        /* fichierBalisesFerme :
     Ferme un fichier prealablement ouvert par fichierBalisesOuvre
        */
        ~FichierBalises()
        {
            fichier.close();
        }
        /* litProchaineBalise :
        Renvoie la prochaine balise présente dans le fichier non encore retournée par litProchaineBalise.
        Saute par-dessus d'éventuelles zones textuelles le cas échéant.
        Lève une exception de type range_error lorsqu'on atteint la fin du fichier (avant qu'une balise n'ait commencé à être spécifiée)
                (par exemple dans le cas d'un fichier se terminant par <TOTO attr1="toto">)
        Lève une exception de type runtime_error lorsqu'on atteint la fin du fichier alors qu'une balise était en cours de lecture
            (par exemple dans le cas d'un fichier se terminant par <TOTO attr1="toto")
        */
        Balise litProchaineBalise()
        {
            string uneBalise = "";
            while (leFichier[position] != '<' && position < leFichier.length())
                position++;
            if (position < leFichier.length())
                do {
                    position++;
                    if (leFichier[position] == '<')
                        throw runtime_error("Caratère d'ouverture de balise à l'intérieur d'une balise!");
                    uneBalise += leFichier[position];
                } while (leFichier[position] != '>' && position < leFichier.length());
            return (Balise(uneBalise));
        }
        private :
            ifstream fichier;
            string leFichier;
            int position;
    };
    #endif

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    74
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Octobre 2006
    Messages : 74
    Points : 52
    Points
    52
    Par défaut Merci
    En effet, c'est là où était le problème... disons que pour ce qui est du c++ je ne suis pas un expert, mais tranquillement je m'améliore....


    Pendant que j'y suis... est-ce normal que lorsque j'utilise mes fichiers (Balise ou FichierBalise), je ne peux faire une affectation directe par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    Balise uneBalise;
    // déjà là ça va pas bien...  il me dit qu'il faut utiliser le constructeur...
    Balise balise2(uneChaine);
     
    uneBalise = balise2;
    dans ma tête à moi, je devrais pouvoir faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Balise uneBalise = new Balise("blahblah");

  4. #4
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Salut,

    Ce qui se passe, c'est que le compilateur est "bête et méchant"

    Quand tu déclare un constructeur qui prend un argument, il s'attend à ce que tu utilise ce constructeur chaque fois que tu veux créer une nouvelle variable

    En fait, il faut être un plus plus précis que cela:

    Si tu ne déclare aucun constructeur, le compilateur en créera un qui ne prend aucun argument, et qui appelle les constructeurs ne prenant pas d'argument des différents membre de ta classe.

    Mais, si tu déclare toi même un constructeur, il ne le fera plus, parce que tu peux souhaiter qu'il n'existe pas de constructeur ne prenant pas d'argument.

    La raison est simple: le rôle d'un constructeur est de fournir un objet... correctement initialisé et donc prêt à servir

    Le compilateur estime donc que, si tu as pris la peine de déclarer un constructeur qui prend des arguments, c'est qu'ils sont nécessaires... pour initialiser l'objet à créer (ca, c'est une belle lapalissade, non )

    Si tu y réfléchis bien, ta classe FichierBalises n'est pas prête à servir si tu ne lui fournis pas le nom du fichier qu'elle doit gérer (imagine si tu essayais d'ouvrir un fichier... dont tu ne connais pas le nom, et que tu arrivais, par le plus grand des hasard à en trouver un (on se demande bien ce qu'il peut contenir) pour essayer d'en lire le contenu... Si tu y arrive, il est temps de jouer au lotto )

    Comme tu as déclaré (et défini) un constructeur qui a besoin d'argument pour "faire son travail", et que, de son coté, le compilateur n'a pas rajouté un constructeur ne prenant aucun argument, il est logique que, lorsque tu essaye de créer une instance de ta classe, il n'accepte que... le fait d'appeler le seul constructeur qu'il connaisse à savoir: le constructeur qui a besoin d'argument pour travailler

    Quand je te disais que le compilateur est "bête et méchant"

    Ceci dit, il ne faut pas confondre la "cause" et "l'effet": Le constructeur est "seulement là" pour... initialiser ton objet.

    Il n'a rien à voir avec l'allocation dynamique de la mémoire pour l'objet lui-même (même s'il peut recourir à l'allocation dynamique de la mémoire pour un de ses membres )

    Par contre, new va effectuer plusieurs choses, parmi lesquelles:
    • Allouer dynamiquement de la mémoire en suffisance pour représenter l'objet
    • Appeler le constructeur afin que la mémoire allouée dynamquement puisse être directement utilisée avec des valeurs "correctement initialisées"
    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

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

Discussions similaires

  1. [PHP 5.2] [POO] Surcharge du constructeur d'une classe
    Par anaranjado dans le forum Langage
    Réponses: 5
    Dernier message: 28/08/2009, 12h23
  2. [POO] Extension de classe et constructeur
    Par grunk dans le forum Langage
    Réponses: 1
    Dernier message: 12/03/2008, 16h37
  3. [POO] Classe et surchage de constructeur
    Par LeXo dans le forum Langage
    Réponses: 3
    Dernier message: 09/07/2007, 18h09
  4. [POO] Classe php5 et constructeur php4
    Par mathrem dans le forum Langage
    Réponses: 1
    Dernier message: 19/03/2007, 17h10
  5. [POO]héritage du constructeur de la classe parente
    Par new_wave dans le forum Langage
    Réponses: 7
    Dernier message: 10/03/2006, 14h25

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