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 :

template et class abstraite


Sujet :

C++

  1. #1
    Membre confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2012
    Messages
    56
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Juin 2012
    Messages : 56
    Par défaut template et class abstraite
    Bonjour à tous,

    Je rencontre un problème de LNK2001 lors d'un build solution, visiblement il n'aime pas mon implémentation au niveau de la classe abstraite.

    J'ai essayé de refaire un code exemple simplifié en se basant sur son architecture:
    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
     
    /* mother.hpp */
     
    template <class result_type>
    class mother
    {
       public:
     
       inline virtual result_type pure_virtual_function() = 0;							
       virtual bool virtual_function();
    }
     
    /* derived.hpp */
     
    template <class result_type>
    class derived : public mother<class result_type>
    {
      public:
     
      inline result_type pure_virtual_function();
    }
     
    /* mother.cpp */
     
    template<class result_type>
    bool mother<result_type>::virtual_function() 
    { 
       pure_virtual_function();
       return true; 
    }
     
    /* derived.cpp */
    template <class result_type>
    inline result_type derived<result_type>::pure_virtual_function() { return -1; }
     
    /* main.cpp */
    int main ()
    {
      mother<int64_t> *m = new derived<int64_t>();
      bool state = m->virtual_function();
      return 0;
    }
    Quelqu'un a une idée ?
    merci.

  2. #2
    Membre Expert
    Avatar de prgasp77
    Homme Profil pro
    Ingénieur en systèmes embarqués
    Inscrit en
    Juin 2004
    Messages
    1 306
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Eure (Haute Normandie)

    Informations professionnelles :
    Activité : Ingénieur en systèmes embarqués
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Juin 2004
    Messages : 1 306

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

    Informations professionnelles :
    Activité : aucun

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

    Déjà, il faut savoir qu'une fonction virutelle inline, cela n'a pas vraiment beaucoup de sens, à cause de la présence d'une vtable (une table des fonctions virtuelles) qui rend quasi impossible l'inlining des fonctions

    Ensuite, il faut savoir qu'une fonction virtuelle (et surtout une fonction virtuelle pure) dans une classe template, cela n'a pas beaucoup de sens non plus, car le propre des template est de définir le type à la compilation alors que le propre des fonctions virtuelles est de le faire à l'exécution.

    En outre, il faut savoir que le retour de la fonction n'est jamais pris en compte dans la résolution des noms, ce qui fait que soit le compilateur se plaindra d'avoir deux déclarations différentes de pure_virtual_function (une renvoyant un booléen et l'autre renvoyant le type indiqué comme paramètre template), soit ca partira en vrille d'une autre manière.

    Enfin, il faut bien avoir conscience du fait que, si A et B sont deux types différents, mother<A> et mother<B> produiront des types totalement différents, présentant certes une interface commune, mais qu'il sera impossible de placer dans une collection hétérogène (un std:::vector<mother<???>* > par exemple).

    Au final, tu as deux solutions:

    Soit, ta classe de base est une classe de base, et, dans ce cas, le mieux est encore de fournir une "spécialisation totale" pour chaque type qui t'intéresse, sous une forme proche de
    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
    template <typename T>
    class Base{
    public:
       inline T foo();
    };
    template <>
    int Base<int>::foo(){
        /* ... */
    }
     
    template <>
    double Base<double>::foo(){
        /* ... */
    }
     
    template <>
    std::string Base<std::string>::foo(){
        /* ... */
    }
    et, pour éviter que l'on puisse instancier directement la classe de base, il "suffit" de placer le constructeur et le destructeur dans l'accessibilité protégée (pour que les classes dérivées puissent y accéder), sous une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    template <typename T>
    class Base{
    protected:
        Base(T t):t_{t}{}
        ~Base(){}
    private:
        T t_;
    }
    class DerivedInt : public Base<int>{
    public:
        DerivedInt(int i) : Base<int>(i){} // OK : DerivedInt peut accéder à tout ce qui est public ou protégé de base
    };
    Soit tu peux faire hériter ta classe template d'une classe de base "classique" (comprends : non template), sous une forme proche de
    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
    class Base{
    public:
        Base(){}
        virtual ~Base(){}
        Base(Base const & ) = delete;
        Base & operator=(Base const & ) = delete;
        vritual void foo() = 0;
    };
    template <typename T>
    class Derived : public Base{
    public:
        /* on sait que cette fonction ne sera pas inline, mais cela permet 
         * de nous assurer que l'éditeur de liens ne s'étonnera pas de trouver
         * plusieurs implémentations de la fonction pour un T donné
         * et donc de respecter l'ODR
         */
        inline void foo() override;
    };
    /* on peut envisager de fournir plusieurs spécialisations totales ;) */
    template <typename T>
    void Dervied<T>::foo(){
        /* ... */
    }
    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. Template dans classe abstraite
    Par Kaluza dans le forum Langage
    Réponses: 6
    Dernier message: 08/11/2011, 07h17
  2. [Smarty] appeler une classe abstraite depuis template
    Par speedev dans le forum Bibliothèques et frameworks
    Réponses: 1
    Dernier message: 23/07/2010, 15h23
  3. Réponses: 2
    Dernier message: 30/12/2009, 20h44
  4. Classe abstraite / MVC
    Par caramel dans le forum MVC
    Réponses: 5
    Dernier message: 01/04/2003, 09h27
  5. pb constructeurs classes dérivant classe abstraite
    Par Cornell dans le forum Langage
    Réponses: 2
    Dernier message: 10/02/2003, 19h02

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