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 :

Problème déclaration anticipée (forward declaration)


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2007
    Messages
    60
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 60
    Par défaut Problème déclaration anticipée (forward declaration)
    Bonjour,

    j'ai un problème avec une déclaration anticipée d'une classe dans le header d'une autre classe. Je m'explique:

    J'ai une classe abonné :
    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
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
     
    //---------- Interface de la classe <Abonne> (fichier Abonne.h) ------
    #if ! defined ( ABONNE_H_ )
    #define ABONNE_H_
     
    //--------------------------------------------------- Interfaces utilisées
     
    #include <string>
    using namespace std;
     
    //------------------------------------------------------------- Constantes
     
    //------------------------------------------------------------------ Types
    class Annuaire;
     
    typedef struct Renseignements{
    	string prenom;
    	string adresse;
    	string telephone;
    	Renseignements(string pren="",string adr="",string tel=""):prenom(pren),adresse(adr),telephone(tel){};
    };
     
     
     
    //------------------------------------------------------------------------
    // Role de la classe <Abonne>
    //
    //
    //------------------------------------------------------------------------
     
    class Abonne
    {
    //----------------------------------------------------------------- PUBLIC
     
    public:
    //----------------------------------------------------- Méthodes publiques
        // type Méthode ( liste des paramètres );
        // Mode d'emploi :
        //
        // Contrat :
        //
     
    	friend void Annuaire::Ajouter(Abonne e);
     
    //------------------------------------------------- Surcharge d'opérateurs
        Abonne & operator = ( const Abonne & unAbonne );
        // Mode d'emploi :
        //
        // Contrat :
        //
     
        friend ostream & operator<<(ostream & flot,const Abonne & unAbonne);
        friend istream & operator>>(istream & flot,Abonne & unAbonne);
     
     
    //-------------------------------------------- Constructeurs - destructeur
        Abonne ( const Abonne & unAbonne );
        // Mode d'emploi (constructeur de copie) :
        //
        // Contrat :
        //
     
        Abonne (string aNom="" , string aPrenom="", string aAdresse="", string aTel="" ):nom(aNom),info(aPrenom,aAdresse,aTel){};
        // Mode d'emploi :
        //
        // Contrat :
        //
     
        virtual ~Abonne ( );
        // Mode d'emploi :
        //
        // Contrat :
        //
     
    //------------------------------------------------------------------ PRIVE
     
    protected:
    //----------------------------------------------------- Méthodes protégées
     
    //----------------------------------------------------- Attributs protégés
    	string nom;
    	Renseignements info;
     
    };
     
    //--------------------------- Autres définitions dépendantes de <Abonne>
     
    #endif // ABONNE_H_
    et une classe annuaire pour gérer une collection d'abonnés avec une multimap.
    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
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
     
    //---------- Interface de la classe <Annuaire> (fichier Annuaire.h) ------
    #if ! defined ( ANNUAIRE_H_ )
    #define ANNUAIRE_H_
     
    //--------------------------------------------------- Interfaces utilisées
    #include "Abonne.h"
    #include <map>
     
    //------------------------------------------------------------- Constantes
     
    //------------------------------------------------------------------ Types
     
    //------------------------------------------------------------------------
    // Role de la classe <Annuaire>
    //
    //
    //------------------------------------------------------------------------
     
    class Annuaire
    {
    //----------------------------------------------------------------- PUBLIC
     
    public:
    //----------------------------------------------------- Méthodes publiques
        // type Méthode ( liste des paramètres );
        // Mode d'emploi :
        //
        // Contrat :
        //
     
    	void Ajouter(Abonne e);
     
    	void Afficher() const;
     
     
    //------------------------------------------------- Surcharge d'opérateurs
        Annuaire & operator = ( const Annuaire & unAnnuaire );
        // Mode d'emploi :
        //
        // Contrat :
        //
     
     
    //-------------------------------------------- Constructeurs - destructeur
        Annuaire ( const Annuaire & unAnnuaire );
        // Mode d'emploi (constructeur de copie) :
        //
        // Contrat :
        //
     
        Annuaire ( );
        // Mode d'emploi :
        //
        // Contrat :
        //
     
        virtual ~Annuaire ( );
        // Mode d'emploi :
        //
        // Contrat :
        //
     
    //------------------------------------------------------------------ PRIVE
     
    protected:
    //----------------------------------------------------- Méthodes protégées
     
    //----------------------------------------------------- Attributs protégés
    	multimap<string,Renseignements> pagesBlanches;
     
    };
     
    //--------------------------- Autres définitions dépendantes de <Annuaire>
     
    #endif // ANNUAIRE_H_
    Le souci se pose au niveau de la fonction Ajouter() de la classe annuaire. Je souhaite ajouter un abonné à l'annuaire. J'ai pour cela défini comme ami la fonction Annuaire::Ajouter dans la classe Abonne. Pour rendre cela possible je souhaite utiliser une déclaration anticipée de la classe Annuaire dans la classe Abonne.

    Mais voilà à la compilation cela ne passe pas :

    forward declaration of «struct Annuaire» Abonne.h Annuaire 20
    invalid use of incomplete type «struct Annuaire» Abonne.h Annuaire 49

    quelqu'un a une idée?

    merci

  2. #2
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Par défaut
    Je ne voie pas pourquoi ta classe "Abonne" a besoin du déclaration forward de la classe "Annuaire". Elle ne l'utilise pas mis à par dans la déclaration "friend". (ou alors, j'ai mal lu)

    Je ne pense que le friend soit obligatoire ni nécessaire d'ailleurs.

    Par contre ta déclaration de la fonction Annuaire::Ajoute() devrait être quelquechose comme cela :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Annuaire::Ajoute(const Abonne & a)
    Tu passes l'abonné par référence ainsi il n'y a pas copie du paramètre.

    Dans ton fichier "Annuaire.h", tu as par contre besoin d'inclure "Abonne.h"
    Raymond
    Vous souhaitez participer à la rubrique Réseaux ? Contactez-moi

    Cafuro Cafuro est un outil SNMP dont le but est d'aider les administrateurs système et réseau à configurer leurs équipements SNMP réseau.
    e-verbe Un logiciel de conjugaison des verbes de la langue française.

    Ma page personnelle sur DVP
    .

  3. #3
    Membre chevronné
    Avatar de Florian Goo
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    680
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Septembre 2008
    Messages : 680
    Par défaut
    Bonjour,

    La déclaration anticipée d'une classe ne déclare que le nom de cette classe. En outre, tous ses membres sont encore inconnus. Annuaire::Ajouter() n'est donc pas encore déclaré et ne peut donc être cité.

    Pourquoi aurais-tu besoin de rendre cette fonction membre friend ? Si tu en as vraiment besoin, tu n'as qu'à rendre la classe Annuaire entièrement friend.


    Deux remarques sans rapport :
    - le typedef de typedef struct est inutile en C++
    - jamais de using namespace dans un .h
    Cours : Initiation à CMake
    Projet : Scalpel, bibliothèque d'analyse de code source C++ (développement en cours)
    Ce message a été tapé avec un clavier en disposition bépo.

  4. #4
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2007
    Messages
    60
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 60
    Par défaut
    bonjour,

    je voulais en fait pouvoir accéder directement aux attributs d'un abonné dans la fonction Ajouter() afin de créer la clé <String nom, Renseignement info> dans la multimap pagesBlanches de Annuaire

  5. #5
    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
    Salut,

    Rien ne sert de rendre une classe amie pour si peu...

    Tu crées, simplement, deux accesseurs constants: l'un pour le nom sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    const std::string& Abonne::getName() const
    {
        return nom;
    }
    et l'autre qui renvoie une référence constante sur les renseignement, et qui prend la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    const Renseignements Abonne::getInfos() const
    {
        return info;
    }
    NOTA: Ces deux méthodes sont des candidates idéales à la déclaration inline

    Dans la classe annuaire, il te "suffira" d'inclure les informations sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void Annuaire::ajouter(const Abonne& ab)
    {
        pagesBlanches.insert(std::make_pair(ab.getName(),ab.getInfos()));
    }
    et le tour est joué

    NOTA 2: même sans déclarer les deux méthodes proposées pour Abonne inline, tu ne dois pas vraiment craindre d'énormes pertes de performances sur ces deux cas bien précis... je présumes que tu fera bien plus de recherches sur les abonnés que d'ajouts

    NOTA 3:Quand tu passe une structure ou une classe en paramètre d'une fonction, prend l'habitude de le passer au minimum par référence, afin d'éviter la copie, et, si la fonction n'a pas besoin de modifier le paramètre, meme en tant que référence constante

    Pour le constructeur de Renseignements, cela donnerait donc
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Renseignements(const string& pren="", 
                   const string& adr="",const string& tel=""):
                   prenom(pren), adresse(adr), telephone(tel){};
    (idem pour le constructeur d'Abonne)

    NOTA 3 bis:le point virgule ";" n'est nécessaire que lorsqu'il s'agit de la déclaration d'une fonction (ou d'une variable).

    Lorsqu'il s'agit de l'implémentation de la fonction les accolades "{" et "}" suffisent

    NOTA 4:En outre (mais je ne fais que le proposer ici), *peut-être* serait il intéressant d'envisager que la responsabilité de la création des abonnés revienne... à l'annuaire

    Tu pourrais alors créer une méthode proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    void Annuaire::createAbonne(const std::string& aNom="" , 
                   const std::string& aPrenom="",  const std::string& aAdresse="", 
                   const std::string& aTel="" )
    {
        Abonne toadd(anom, aprenon, aAdresse,aTel);
        info.insert(std::make_pair(anon,toadd));
    }
    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 forward declaration
    Par gregleboss50 dans le forum Langage
    Réponses: 10
    Dernier message: 08/08/2014, 07h20
  2. Problème de forward declaration
    Par le_ptit_lutin dans le forum C++
    Réponses: 10
    Dernier message: 02/07/2012, 17h55
  3. Problème de "forward declaration"
    Par oodini dans le forum C++
    Réponses: 8
    Dernier message: 09/03/2009, 18h05
  4. has incomplete type,forward declaration of ,
    Par Pragmateek dans le forum C++
    Réponses: 12
    Dernier message: 22/07/2006, 15h03
  5. [JS] Problème déclaration de fonction
    Par glloq8 dans le forum Général JavaScript
    Réponses: 5
    Dernier message: 23/09/2005, 10h22

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