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

Langage C++ Discussion :

Factorisation des membres d'une classe template


Sujet :

Langage C++

  1. #1
    Membre émérite
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 764
    Points : 2 705
    Points
    2 705
    Par défaut Factorisation des membres d'une classe template
    Bonjour,

    Soit la classe suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    template <typename T>
    struct C
    {
        int var1;
        static int var2;
        vector<T> var3;
    };
    Est-il intéressant de factoriser comme suit :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    struct A
    {
        int var1;
    };
     
    template <typename T>
    struct B : public A
    {
        static int var2;
        vector<T> var3;
    };
    Si la réponse est négative, est-elle toujours valide si je remplace la donnée membre var1 par une fonction fnc1() ?

    Merci.

  2. #2
    Membre émérite
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 764
    Points : 2 705
    Points
    2 705
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    B est-elle censée hériter de A? Pour moi, ce serait le plus équivalent au cas C...
    Effectivement. J'ai corrigé.

  3. #3
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Autant pour une variable seule ça me paraît beaucoup de bruit pour rien, autant pour des fonctions ça peut être intéressant.

    La chose à ne pas oublier par contre, c'est que ta classe est censée être polymorphique ou ne l'est pas: Le destructeur de A devrait être soit public et virtuel, soit protected et non-virtuel.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  4. #4
    Membre émérite
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 764
    Points : 2 705
    Points
    2 705
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    Autant pour une variable seule ça me paraît beaucoup de bruit pour rien,
    Pour rien, ou pour pas grand chose ?
    Car s'il n'y a qu'une seule variable, c'est parce que j'ai voulu présenter un exemple simplifié.

    Pour moi, les variables membres sont portées par les instances, et peu importe donc qu'elles soient déclarées dans de multiples définitions de classe après instanciation des templates.

    En revanche, les définitions de fonctions (et les données membre statique) sont portées par les définitions de classe, et donc 10 instanciations différentes généreront 10 définitions de fonction, alors que pour les fonctions non dépendantes du template, une seule suffirait.

    Mais je ne suis pas sûr de mon coup à 100%.

  5. #5
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Pour les fonctions, oui, c'est intéressant.
    Visual merge généralement les fonctions qui ont le même code dans la build Release (au grand dam du debugger), mais j'ignore ce que font les autres compilos.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  6. #6
    Membre émérite
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Points : 2 799
    Points
    2 799
    Par défaut
    Personnellement, si vraiment le but est de factoriser des fonctions, je le ferai plutôt par composition :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    struct A
    {
        int var1;
    };
     
    template <typename T>
    struct B
    {
        A a;
        static int var2;
        vector<T> var3;
    };
    Et pour chaque fonction publique de A, tu peux si tu y tiens créer une fonction inline identique dans B (qui donc, ne génèrera pas forcément de symbole).

  7. #7
    Membre émérite
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 764
    Points : 2 705
    Points
    2 705
    Par défaut
    Citation Envoyé par white_tentacle Voir le message
    Personnellement, si vraiment le but est de factoriser des fonctions, je le ferai plutôt par composition
    Ah... Le grand débat entre la composition et l'héritage...

    Merci en tout cas pour vos réponses !

  8. #8
    Membre chevronné Avatar de Astraya
    Homme Profil pro
    Consommateur de café
    Inscrit en
    Mai 2007
    Messages
    1 043
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France

    Informations professionnelles :
    Activité : Consommateur de café
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2007
    Messages : 1 043
    Points : 2 234
    Points
    2 234
    Par défaut
    Je trouve ça étrange comme question... La réponse va uniquement dépendre de la nature de A et B....
    Est-ce que A est forcement composé d'un int? Est-ce que B peut être traité comme un A ou est ce que B est uniquement un B et que il a besoin d'un A pour vivre . Est-ce que B à la particularité d'avoir un int que A n'a pas?
    Bref je pense pas qu'un réponse universel existe ^^
    Homer J. Simpson


  9. #9
    Membre émérite
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 764
    Points : 2 705
    Points
    2 705
    Par défaut
    Citation Envoyé par Astraya Voir le message
    Est-ce que A est forcement composé d'un int ?
    Non.
    En fait, ce sont plutôt des string.

    Citation Envoyé par Astraya Voir le message
    Est-ce que B peut être traité comme un A ou est ce que B est uniquement un B et que il a besoin d'un A pour vivre.
    Pas d'utilisation polymorphique.

    Citation Envoyé par Astraya Voir le message
    Est-ce que B à la particularité d'avoir un int que A n'a pas ?
    Oui.

  10. #10
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Salut,

    Pour ma part je trouve ca intéressant... si A est utilisée ailleurs que dans B (ailleurs pouvant être en stand-alone)
    Sinon, inutile! ^^
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  11. #11
    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,

    Le SRP et l'ISP (bon, en n'est pas en voiture, hein, je parle de Single Responsability Principle et de Interface Segregation Principle ) devraient t'inciter à avoir un grand nombre de petites classes ou structures très spécialisées et à les assembler "comme des légos".

    Chaque petite classe ou structure prendrait alors un aspect particulier du problème en charge, sans s'inquiéter du reste, et pourrait s'en occuper correctement.

    De cette manière, tu arriveras à créer des classes qui ne se retrouvent pas à se trimbaler une fonction "machin" qui utilise un tas de données dont tu n'as strictement que faire, mais qui étaient utile pour une ou deux classes bien particulières.

    L'énorme avantage qu'il y a à travailler de la sorte est que tu arrives à garder tes fonctions les plus utilisées particulièrement simple: un test, une boucles, quelques instructions... emballez, c'est pesé.

    Ca devient beaucoup plus facile à tester, il devient beaucoup plus facile de prouver que "ca marche dans n'importe quelle circonstance", ca devient plus facile à maintenir parce que, si problème il y a dans une fonction qui utilise ce "concept minimal", ce n'est surement pas dans cette petite fonction (une fois que tu as prouvé qu'elle fonctionnait correctement, s'entend).

    Alors, y a-t-il vraiment intérêt à le faire très certainement si tu es face à deux concepts très clairement distincts, "transversaux", fortement indépendants et susceptibles d'être utilisés l'un sans l'autre en différentes occasions
    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

  12. #12
    Expert confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Points : 4 442
    Points
    4 442
    Par défaut
    J'arrive un peu en retard, mais quel est l'intérêt de ce genre de choses ?

    Pour une fonction ça peut éviter qu'elle soit générée plusieurs fois par le compilo et réduire la taille de l’exécutable (enfin je suppose ?)

    Mais pour une variable membre ?

  13. #13
    Membre émérite
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 764
    Points : 2 705
    Points
    2 705
    Par défaut
    Citation Envoyé par Iradrille Voir le message
    J'arrive un peu en retard, mais quel est l'intérêt de ce genre de choses ?
    La question était justement de savoir si cela avait un intérêt.

  14. #14
    Membre expérimenté

    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2011
    Messages
    685
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2011
    Messages : 685
    Points : 1 418
    Points
    1 418
    Par défaut
    Dans ce cas je suis d'accord avec Bousk et Koala01 à la fois.

    Si A n'est pas réutilisée ailleurs, aucun intérêt. Sinon, tout dépend de tes besoins mais il y a tout intérêt à le faire (bon pour un type primitif je sais pas trop mais pour une fonction), sans oublier de respecter SOLID comme l'a dit Koala01

    @white_tentacle : je connaissais pas ce truc tu peux développer ?
    Nullius in verba

  15. #15
    Membre émérite
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 764
    Points : 2 705
    Points
    2 705
    Par défaut
    Il ne faut pas oublier qu'il y avait 2 réponses à fournir (var/fnc1).
    Et tu as reposé ces 2 questions dans ton avant-dernier message

  16. #16
    Membre émérite
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Points : 2 799
    Points
    2 799
    Par défaut
    Citation Envoyé par Kaamui Voir le message
    Dans ce cas je suis d'accord avec Bousk et Koala01 à la fois.

    Si A n'est pas réutilisée ailleurs, aucun intérêt. Sinon, tout dépend de tes besoins mais il y a tout intérêt à le faire (bon pour un type primitif je sais pas trop mais pour une fonction), sans oublier de respecter SOLID comme l'a dit Koala01

    @white_tentacle : je connaissais pas ce truc tu peux développer ?
    Les fonctions inline ne génèrent pas d’appel de fonction (et, je crois, pas forcément un symbole, mais là c’est à vérifier).

    Donc si tu écris ta classe de la sorte :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    class B
    {
       A a;
    public:
       void doSomething { a.doSomething(); }
    }
    …
     
    B b;
    b.doSomething();
    L’appel sera aussi performant que si tu avais fait :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    class A
    {
    public:
        A a;
    }
    …
     
    B b;
    b.a.doSomething();

  17. #17
    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
    Citation Envoyé par white_tentacle Voir le message
    Les fonctions inline ne génèrent pas d’appel de fonction (et, je crois, pas forcément un symbole, mais là c’est à vérifier).

    Donc si tu écris ta classe de la sorte :

    L’appel sera aussi performant que si tu avais fait :
    Enfin, ca, c'est la théorie...

    Car, en pratique, le compilateur reste libre de faire à peu près ce qu'il veut, en fonction du nombre de commandes processeur qu'il a du générer pour la fonction.

    On peut bien sur essayer de jouer avec foceinline et le nombre d'instructions qu'il accepte d'inliner, ou avec des options d'optimisation de la sortie, mais il ne faut pas trop se fier à cette théorie car il y a énormément de cas où cela reviendra au même

    Il ne faut pas oublier non plus que l'appel d'une fonction au niveau processeur se limite à peu de choses près un push ou l'autre avant l'appel et à un pop au retour.

    Le gain de performances n'est donc sensible que sur des fonctions relativement courtes (en terme de temps d'exécution processeur) et souvent appelé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

  18. #18
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Enfin, vu que des accesseurs et des forwardeurs d'appel sont plus courts ou de même taille que l'appel lui-même, seul un mauvais compilo refuserait de les inliner.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

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

Discussions similaires

  1. Réponses: 1
    Dernier message: 12/11/2013, 13h22
  2. Spécialisation de membre d'une classe template
    Par Rewpparo dans le forum Langage
    Réponses: 17
    Dernier message: 10/04/2012, 11h13
  3. Réponses: 9
    Dernier message: 12/07/2010, 14h25
  4. créer automatiquement des membres dans une classe
    Par katebe dans le forum Windows Forms
    Réponses: 15
    Dernier message: 08/01/2008, 11h21
  5. Parcours des membres d'une classe
    Par Isildur dans le forum WinDev
    Réponses: 5
    Dernier message: 13/10/2006, 09h13

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