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 :

entêtes croisées et templates


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé Avatar de BioKore
    Homme Profil pro
    Dresseur d'Alpaga
    Inscrit en
    Septembre 2016
    Messages
    300
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Dresseur d'Alpaga

    Informations forums :
    Inscription : Septembre 2016
    Messages : 300
    Par défaut entêtes croisées et templates
    Bonjour à tous,

    Je réalise un code sur deux fichiers d'entête séparés. A.hpp et B.hpp. Comme l'indique le titre du sujet, A a besoin de B et B a besoin de A.
    Dans un cas normal, je dirais, pas de soucis ; je créé les mêmes en *.cpp et le tour est joué. Mon problème ici c'est que j'ai des classes templates et des fonctions membres templates. Donc si je fait des définitions dans un fichier *.cpp, je vais être obligé de définir les templates pour chaque type que je souhaite utiliser. Il est hors de question que je fasse le boulot que les templates sont justement sensées faire.
    Mon code commence a avoir une certaine complexité (à mon niveau), et j'en ai un peu marre de tester les différentes solutions possibles pour réussir à faire fonctionner les templates buguées de C++ (oui, soyez honnêtes, l'idée des templates est bonne mais leur utilisation est quand même mal foutue).

    C'est grandement simplifié, mais voici la forme du code :
    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
     
    ///// Name.hpp
     
    template<typename T>
    class Name
    {
    private:
     
    	Company nComp;
     
    public:
     
    	template<typename C>
    	void foo()
    	{
    		//[...];
    	}
     
    };
     
    ///// Company.hpp
     
    class Company
    {
    private:
     
    public:
     
    	template<typename T>
    	Name<T> & foo()
    	{
    		//[...];
    	}
    };
    Alors j'ai bien-entendu essayé de faire des déclarations anticipées dans les deux headers, mais évidement "invalid use of incomplete type". Si je réalise les définitions dans des *.cpp séparés, j'ai des "undefined reference to Name::foo<T> etc..." parce que je n'ai pas envie d'obliger l'utilisateur (moi-même en l’occurrence) de devoir spécialiser le template pour chaque type que je vais utiliser (on utilise les templates pour éviter ça justement non ?) sur toute la palanquée de fonctions templatées de mes classes.

    Quelqu'un saurait m'aiguiller sur une solution ? Je peux fournir le code complet si besoin mais je pense que les quelques lignes ci-dessus représentent bien l'idée générale.

    Merci d'avance !

    Désoler pour ce message un peu direct, mais ce genre de blocages liées à la viscosité de ce langage ont tendance à m'irriter

  2. #2
    Invité
    Invité(e)
    Par défaut
    Bonsoir,

    Étant donné le membre Company nComp; de la classe template Name, tu n'as déjà pas le choix : il te faut obligatoirement inclure Company.hpp avant.
    Mais pour ce qui de la fonction membre Company::foo(), une déclaration anticipée de la classe Name suffit. Mais attention, si tu manipules un objet Name dedans, il te faut obligatoirement l'implémenter à l'extérieur, une fois que tu auras inclus Name.hpp.

    Pour plus de détails cf. Le problème d'inclusion circulaire / la « forward declaration »

    Ce qui donnera :

    Name.hpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #include "Compagny.hpp"
     
    template<typename T>
    class Name
    {
    private:
     
    	Company nComp;
     
    	...
     
    };
    Company.hpp
    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
    // déclaration anticipée
    template<typename T>
    class Name;
     
    class Company
    {
    private:
     
    public:
     
    	// déclaration
    	template<typename T>
    	Name<T> & foo();
    };
     
    #include "Company.tpp"
    Company.tpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    #include "Name.hpp"
     
    // implémentation, une fois le fichier Name.hpp inclus
    template<typename T>
    Name<T> & Company::foo() {
        ...
    }

  3. #3
    Membre éclairé Avatar de BioKore
    Homme Profil pro
    Dresseur d'Alpaga
    Inscrit en
    Septembre 2016
    Messages
    300
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Dresseur d'Alpaga

    Informations forums :
    Inscription : Septembre 2016
    Messages : 300
    Par défaut
    Merci pour le retour.

    En fait, que ce soit dans les fonctions de "Company" ou de "Name", chacune de ces classes manipulent des objets de l'autre.

    Les fonctions de Company manipulent et modifient des objets de Name et vice-versa... Bon,visiblement je vais donc travailler avec des fichiers séparés.

    Après, faut voir le code actuel, il est peut être possible d'en arriver au même résultat avec deux classes distinctes et mieux faites mais je dois trouver la solution. Pour le moment j'en suis là.

    Merci pour ce retour.

  4. #4
    Membre Expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2011
    Messages
    767
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2011
    Messages : 767
    Par défaut
    Pour les templates, la déclaration anticipée suffit à écrire l'implémentation. Ce n'est pas gênant que Name n'existe pas du moment que son instanciation dépend d'un type template (comme avec Company::foo()).

    En gros, Company::foo<T>() n'a pas besoin de connaître l'implémentation de Name puisqu'elle ne connaît pas le type de T. Si elle n'a pas T, elle ne peut pas avoir Name<T>. C'est seulement au moment de l'appel de la fonction que Name<T> doit être définie car à ce moment T est connue. Il faut bien comprendre qu'à moins de faire des instanciations explicites, les templates ne sont compilées qu'au moment de leur utilisation.

    Ceci explique aussi pourquoi il n'est pas possible de mettre les templates dans un .cpp: le fichier ne les utilisent pas, elles n'existent donc pas dans cette unité de compilation. Comme le .cpp est le seul avec l'implémentation aucune des fonctions templates n'est compilées. C'est pour cela que les templates doivent être dans un .h.

  5. #5
    Expert confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 543
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 543
    Par défaut
    Pour compléter la réponse de @jo_link_noir, en POO, on a tendance à découpler les classes.
    Ici, pour utiliser Name, vous devez connaitre Company ; et pour utiliser Company, vous devez connaitre Name.
    C'est très mauvais au niveau découplage.
    C'est un peu comme, "pour utiliser une banane, il me faut le singe qui tient la banane, pour récupérer le singe, je dois récupérer l'arbre où est le singe, pour récupérer l'arbre, il faut récupérer le forêt où est l'arbre, etc..."
    En clair, je ne vois aucune justification à ce que "Name" est besoin de "Company".

  6. #6
    Membre éclairé Avatar de BioKore
    Homme Profil pro
    Dresseur d'Alpaga
    Inscrit en
    Septembre 2016
    Messages
    300
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Dresseur d'Alpaga

    Informations forums :
    Inscription : Septembre 2016
    Messages : 300
    Par défaut
    Bonjour, et merci pour ce retour.

    Effectivement, bien que j'ai réussi à réaliser ce couplage, je me suis ré-orienté vers un fonctionnement n'en ayant plus besoin.
    Étant relativement débutant en programmation, je dois apprendre a prendre plus de recul par rapport aux objectifs de mon code, mais étant autodidacte et sans objectif logiciel précis, je me retrouve régulièrement dans ce genre de situations.

    Cependant je viens de trouver un exercice qui me semble assez intéressant pour apprendre à éviter de tomber dans le panneau. Bien que, justement, j'essaie de répondre à ce problème sans passer par la POO (en tout cas, le moins possible), ce dernier à l'air très formateur. Et puis ça me donne justement un "objectif logiciel" derrière la formation apportée.

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

Discussions similaires

  1. [AC-2003] Forcer les entêtes d'une requête croisée ?
    Par marot_r dans le forum Requêtes et SQL.
    Réponses: 9
    Dernier message: 14/01/2011, 13h43
  2. Templates, dependance croisée, specialisation
    Par Glacius dans le forum Langage
    Réponses: 10
    Dernier message: 10/07/2009, 14h36
  3. [Template] problème de références croisées
    Par ded jay dans le forum C++
    Réponses: 3
    Dernier message: 24/08/2008, 16h20
  4. Réponses: 5
    Dernier message: 27/01/2008, 18h04
  5. Requête croisée et entête de colonnes
    Par mariemor64 dans le forum Requêtes et SQL.
    Réponses: 1
    Dernier message: 08/01/2007, 15h43

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