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 :

Type de class et arguments pour fonctions et new


Sujet :

C++

  1. #1
    Membre habitué
    Inscrit en
    Décembre 2004
    Messages
    188
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 188
    Points : 143
    Points
    143
    Par défaut Type de class et arguments pour fonctions et new
    Bonjour, voici ce que je voudrais faire, je ne sais pas si c'est possible en C++ :
    - passer un type comme argument d'une fonction
    - utiliser ce type comme paramètre de new

    Imaginons une classe base, avec des descendants (fille1, fille2,...) où type_class_base représente le type class base et ses descendants éventuels, et type_class un type de la famille de types type_class_base.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    void func(type_class_base type_class)
    {
       base *newvar;
     
       newvar = new type_class(); 
    }
    ...
    func(fille2); // Création d'une instance de la class fille2
    Merci pour votre aide

  2. #2
    Membre confirmé Avatar de toxcct
    Développeur informatique
    Inscrit en
    Juillet 2006
    Messages
    434
    Détails du profil
    Informations personnelles :
    Âge : 42

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Juillet 2006
    Messages : 434
    Points : 511
    Points
    511
    Par défaut
    tu veux faire un template quoi ...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    template<T> func() {
        Base* pBase = new T;
    }

  3. #3
    Membre habitué
    Inscrit en
    Décembre 2004
    Messages
    188
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 188
    Points : 143
    Points
    143
    Par défaut
    C'est un peu comme un template, sauf que dans ce cas je veux restreindre le type T à la classe Base et ses descendants (et je voudrais éviter que la classe Base soit template)

  4. #4
    Membre confirmé Avatar de toxcct
    Développeur informatique
    Inscrit en
    Juillet 2006
    Messages
    434
    Détails du profil
    Informations personnelles :
    Âge : 42

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Juillet 2006
    Messages : 434
    Points : 511
    Points
    511
    Par défaut
    Citation Envoyé par Alfred12
    C'est un peu comme un template, sauf que dans ce cas je veux restreindre le type T à la classe Base et ses descendants (et je voudrais éviter que la classe Base soit template)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    template<T> func() {
        if (T typeof Base) {
            Base* pBase = new T;
        }
    }
    je ne connais pas la syntaxe exacte du typeof, mais il sert a ce genre de chose... évidemment, si tu passes un type qui hérite de Base, ca marchera aussi

  5. #5
    Membre habitué
    Inscrit en
    Décembre 2004
    Messages
    188
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 188
    Points : 143
    Points
    143
    Par défaut
    J'ai écrit ca, ca passe à la compil mais je ne sais pas comment appeler func()
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class base
    {
    public:
       template <typename T> func();
    };
     
    template <typename T> func()
    {
       if (T == typeof(base)) {
          base *obj = new T;
       }
    }

  6. #6
    Membre habitué
    Inscrit en
    Décembre 2004
    Messages
    188
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 188
    Points : 143
    Points
    143
    Par défaut
    mais je ne sais pas comment appeler func()
    Si, a priori ca devrait être :

  7. #7
    Membre confirmé Avatar de toxcct
    Développeur informatique
    Inscrit en
    Juillet 2006
    Messages
    434
    Détails du profil
    Informations personnelles :
    Âge : 42

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Juillet 2006
    Messages : 434
    Points : 511
    Points
    511
    Par défaut
    je me demande s'il ne faut pas mettre la classe en template aussi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    template<T> class base { ... };
    et apres, tu l'apelles dans ce style la :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    base<MonType> b;
    b.func();

  8. #8
    Membre habitué
    Inscrit en
    Décembre 2004
    Messages
    188
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 188
    Points : 143
    Points
    143
    Par défaut
    D'après le Mega Cours C++, il est possible d'avoir une fonction template dans une classe qui ne l'est pas.

    En fait j'ai un problème à la compilation (référence externe non-trouvée sur ma fonction template). J'ai aussi essayé de faire une fonction template à l'extérieur de ma classe et j'ai le même problème.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    template <typename T> void func()
    {
        base *obj = new T;
    }
    ...
    func<fille>();  // Référence externe non-trouvée

  9. #9
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Citation Envoyé par Alfred12
    Bonjour, voici ce que je voudrais faire, je ne sais pas si c'est possible en C++ :
    - passer un type comme argument d'une fonction
    - utiliser ce type comme paramètre de new
    Tu veux du polymorphisme parametrique. La voie normale en C++ c'est d'utiliser les template:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    template<typename T>base* func() {
       return new T();
    }
     
    base* x = func<fille>();
    avec la contrainte que le type soit connu a la compilation. Si ce n'est pas le cas, on peut l'exprimer d'une autre maniere en utilisant les autres polymorphismes disponibles. Il nous faut un objet pour representer le type et que cet objet puisse fournir un pointeur vers un objet construit par defaut:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    struct baseBuilder {
       virtual base* build() const {return new base(); } // ou = 0?
    };
    Il faut de tels objets pour tous les descendants de base, donc
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    template <typename T> class baseDescendantBuilder: public baseBuilder {
       base* build() const { return new T(); }
    };
    func est alors simplement:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    base* func(baseBuilder const& builder) {
       return builder.build();
    }
     
    ...
    base* x = func(baseDescendantBuilder<fille>());
    ...
    C'est plus complique que le code precedant, mais on peut trimbaler des references ou des pointeurs vers les descendant de baseBuilder. On peut faire de celui-ci un singleton si besoin est.

    De la on peut aussi partir dans au moins trois directions:
    - etendre baseBuilder pour construire aussi d'autres types. Il est maintenant mal nomme, mais on arrive au pattern factory.
    - etendre baseBuilder pour contenir d'autres information sur le type. Ca permet de faire une sorte d'introspection et on se retrouve avec une extension du RTTI et quelque chose de semblable aux meta-classes d'autres langages.
    - fusionner baseBuilder avec base (on appelle alors generalement build() clone() et on lui fait generer une copie de l'objet sur lequel on l'appelle plutot qu'un objet construit par defaut).

  10. #10
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Citation Envoyé par Alfred12
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    template <typename T> void func()
    {
        base *obj = new T;
    }
    ...
    func<fille>();  // Référence externe non-trouvée
    Je ne vois rien de bizarre. Donne un code complet, minimal et ne presentant que l'erreur qui te preoccupe ici.

  11. #11
    Membre habitué
    Inscrit en
    Décembre 2004
    Messages
    188
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 188
    Points : 143
    Points
    143
    Par défaut
    Je ne vois rien de bizarre.
    Effectivement, j'avais mis le code du template dans le fichier .cpp. Dans le fichier d'entête ca marche beaucoup mieux.

    Merci pour cette réponse détaillée. En fait je ne sais pas encore si j'aurais besoin de la seconde solution que je vais regarder de près mais la première, suggérée aussi par toxcct, fonctionne maintenant et correspond à mes besoins immédiats.



    if (T == typeof(base)) {
    base *obj = new T;
    }
    En fait ca ne compile pas du tout et c'est inutile car si T n'est pas de type base le code ne compile pas.

  12. #12
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Citation Envoyé par Alfred12
    Effectivement, j'avais mis le code du template dans le fichier .cpp. Dans le fichier d'entête ca marche beaucoup mieux.
    J'aurais du y penser. C'est une

  13. #13
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 282
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 282
    Points : 11 036
    Points
    11 036
    Par défaut
    On peut utiliser le SFINAE pour détecter si la classe reçue dérive bien publiquement de Base. Je suppose qu'avec les concepts du C++09, on pourra faire des trucs encore plus propres.

    Il y a des trucs pour faire ça dans Loki (qui sont détaillé dans une section d'un chapitre de Modern C++ Design), et probablement dans boost aussi.

  14. #14
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Citation Envoyé par Luc Hermitte
    On peut utiliser le SFINAE pour détecter si la classe reçue dérive bien publiquement de Base.
    On veut ici que l'instanciation échoue dans ce cas, ce qu'elle fait toute seule... qu'apporterait SFINAE?

  15. #15
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 282
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 282
    Points : 11 036
    Points
    11 036
    Par défaut
    Des macros qui vont permettre des choses un chouilla plus génériques, qui permettront à leur tour de renvoyer un T* plutôt qu'un Base*, tout en apportant la contrainte, et sans jouer avec des casts explicites.

    Si renvoyer un Base* suffit. Et bien .. ca suffit effectivement amplement

  16. #16
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Points : 4 625
    Points
    4 625
    Par défaut
    Y'a les type traits de TR1 pour ça (qui proviennent de boost).
    is_base_of permet en particulier de savoir si un type est une base ou est dérivé d'un autre type.

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

Discussions similaires

  1. Passer une class comme argument de fonction
    Par Pelote2012 dans le forum Développement Web avec .NET
    Réponses: 2
    Dernier message: 07/08/2014, 13h03
  2. [XE2]Type de classe en paramètre de fonction
    Par Papy214 dans le forum Langage
    Réponses: 5
    Dernier message: 09/05/2012, 12h21
  3. Type d'argument pour appel de fonction dans une DLL
    Par Lio590 dans le forum API, COM et SDKs
    Réponses: 3
    Dernier message: 06/07/2011, 17h28
  4. Réponses: 14
    Dernier message: 26/01/2011, 23h18
  5. [.NET2.0][C#]Passage type de classe dans une fonction
    Par SLE dans le forum Windows Forms
    Réponses: 4
    Dernier message: 06/06/2006, 16h48

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