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 :

Déclaration anticipée ou destructeur par défaut?


Sujet :

C++

  1. #1
    Membre expérimenté
    Homme Profil pro
    Chercheur
    Inscrit en
    Mars 2010
    Messages
    1 218
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Chercheur

    Informations forums :
    Inscription : Mars 2010
    Messages : 1 218
    Points : 1 685
    Points
    1 685
    Par défaut Déclaration anticipée ou destructeur par défaut?
    Bonjour,

    lorsque vous déclarez une nouvelle classe, privilégiez-vous la version avec déclaration anticipée des types des données membres
    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
    class Bar;
    class Foo
    {
     
    public:
     
      Foo(int arg) : m_data(new Bar(arg))
      {}
     
      ~Foo()
      { delete m_data; }
     
    private:
     
      Bar* m_data;
     
    };
    ou la version avec destructeur par défaut?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    #include "bar.hpp"
    class Foo
    {
     
    public:
     
      Foo(int arg) : m_data(arg)
      {}
     
    private:
     
      Bar m_data;
     
    };
    J'utilise souvent la seconde pour gagner en performance sur la destruction des objets mais je me demande si ce n'est pas un mauvais réflexe.

    Quel choix faites-vous en pratique et pourquoi?

    Merci pour vos réponses!

  2. #2
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 012
    Points : 23 145
    Points
    23 145
    Par défaut
    Bonjour,

    La seconde solution a le mérite de respecter les principes RAII, on aura donc moins de risques d'avoir des fuites mémoires.
    De plus, tu ne devrais pas avoir de problèmes du type :
    • ma classe A contient un B ;
    • ma classe B contient un A ;

    Car cela entraînerait une boucle infinie.

    Pour la première solution, on préférera utiliser des pointeurs intelligents, mais dans ce cas là on ne devrait pas pouvoir utiliser de déclaration anticipée (*) ce qui serait utile uniquement dans le cas où l'instance de Bar peut changer dans ta classe Foo.
    Par contre, si tu te retrouves dans le cas :
    • ma classe A peut contenir un B ;
    • ma classe B peut contenir un A ;

    Tu sera obliger de passer par un pointeur nu si ne ne me trompe.

    * après de rapides tests, il est possible d'utiliser des pointeurs intelligents avec une déclaration anticipée, pourtant il me semblait que cela posait problème (?).
    Alors je ne sais pas si j'ai rêvé ou si le problème existait avec g++ < 4.9 (?).

  3. #3
    Membre expérimenté
    Homme Profil pro
    Chercheur
    Inscrit en
    Mars 2010
    Messages
    1 218
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Chercheur

    Informations forums :
    Inscription : Mars 2010
    Messages : 1 218
    Points : 1 685
    Points
    1 685
    Par défaut
    Salut Neckara,

    merci beaucoup pour ta réponse.

    Dans les deux cas, le RAII est respecté donc ça ne me paraît pas être un bon critère pour trancher.

    Le problème des définitions circulaires est effectivement résolu par les déclarations anticipées mais ma question porte plutôt sur le meilleur choix à faire en l'absence de ce problème (puisque dans le cas contraire il n'y a plus de choix).
    On pourrait privilégier la solution qui permet d'éliminer un problème seulement potentiel mais c'est une mauvaise pratique en général (YAGNI).
    Si on suivait ce principe, tous les destructeurs seraient virtuels.

    La question des pointeurs intelligents ne concerne pas directement mon problème.

    Ma question porte réellement sur le meilleur choix à faire quand ce choix se présente effectivement.

  4. #4
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 012
    Points : 23 145
    Points
    23 145
    Par défaut
    Citation Envoyé par Aleph69 Voir le message
    Dans les deux cas, le RAII est respecté donc ça ne me paraît pas être un bon critère pour trancher.
    La première méthode n'est pas du RAII car tu ne "lie" pas la durée de vie l'objet à la durée de vie de ton instance. En effet, tu libères toi-même la ressource "à la main" dans le destructeur.

    Ainsi, si un jour tu oublies de faire un delete (ça peut arriver même aux plus expérimentés), tu auras une fuite de mémoire ou une ressource non libérée.

  5. #5
    Membre expérimenté
    Homme Profil pro
    Chercheur
    Inscrit en
    Mars 2010
    Messages
    1 218
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Chercheur

    Informations forums :
    Inscription : Mars 2010
    Messages : 1 218
    Points : 1 685
    Points
    1 685
    Par défaut
    Le principe RAII consiste justement à acquérir les ressources à l'initialisation (constructeur) et à les libérer à la destruction.
    L'exemple
    n'aboutit à aucune fuite mémoire.
    Je ne peux pas oublier de "delete" puisque je n'en ai pas besoin.

  6. #6
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 012
    Points : 23 145
    Points
    23 145
    Par défaut
    Citation Envoyé par Aleph69 Voir le message
    Je ne peux pas oublier de "delete" puisque je n'en ai pas besoin.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
      Foo(int arg) : m_data(new Bar(arg))
      {}
     
      ~Foo()
      { delete m_data; }
    Ici, tu peux oublier le "delete".

  7. #7
    Membre expérimenté
    Homme Profil pro
    Chercheur
    Inscrit en
    Mars 2010
    Messages
    1 218
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Chercheur

    Informations forums :
    Inscription : Mars 2010
    Messages : 1 218
    Points : 1 685
    Points
    1 685
    Par défaut
    Si on suit ton raisonnement, le RAII est violé partout où il y a acquisition de ressources puisque la mise en place du RAII requiert de mettre un destructeur dans le destructeur à un moment ou à un autre.
    Est-ce que std::vector viole le RAII pour toi?

  8. #8
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 012
    Points : 23 145
    Points
    23 145
    Par défaut
    Le but, d'un objet RAII, c'est de faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    class Toto
    {
         std::vector<int> m_vector;
    }
    Quoiqu'il arrive, m_vector sera alloué à la construction et désalloué à la destruction.

    Si tu utilises à la place :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    class Toto
    {
         std::vector<int> * m_vector;
    }
    Tu n'est alors pas obligé de l'allouer à la construction et de le désallouer à la destruction. Tu peux même désallouer et réallouer en cours d'exécution.
    Ce n'est pas vraiment le but du RAII.

  9. #9
    Membre chevronné Avatar de Ehonn
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    788
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2012
    Messages : 788
    Points : 2 160
    Points
    2 160
    Par défaut
    Le RAII n'est pas violé si la classe qui encapsule un pointeur (ou autre) fait "la bonne chose".

    Pour moi le souci avec la première version est :
    - C'est "compliqué" car cela amène tous les souci de l'allocation dynamique
    - Si cela a du sens, il faudra retaper le constructeur par défaut, le constructeur de copie, l'opérateur d'affectation, ... (la règle des 5 + std::swap)
    (- Et je n'arrive pas à le compiler sans avoir une erreur d'utilisation de type incomplet avec new)

  10. #10
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 012
    Points : 23 145
    Points
    23 145
    Par défaut
    Peut-être un exemple plus parlant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    class Foo
    {
           Foo(void) : m_toto(new Toto){}
           ~Foo(void){ delete m_toto; }
           Toto * m_toto;
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    class Foo
    {
           Foo(void){ m_toto.allocate(); }
           ~Foo(void){ m_toto.desallocate(); }
           Toto m_toto;
    }

    De plus, ne pas oublier qu'un pointeur nu n'est pas RAII, les ressources ne sont pas libérés à sa destruction.
    Les deux codes reviennent au même alors que dans le premier cas, Toto est RAII et pas dans le second cas.
    Pour moi, le RAII, ce n'est pas seulement l'implémentation d'une classe mais aussi son usage, si on fait des classes RAII sans tirer profit du RAII, faire du RAII est alors inutile.
    Donc pour moi le code ne respecte pas le RAII dans l'usage qui en est fait.

    Pour faire un parallèle, c'est comme dire "moi j'utilise des pointeurs intelligents" et faire des horreurs du genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    std::shared_ptr<int> f(&monInt);
    std::shared_ptr<int> fbis( f.get() );
    De plus, ne pas oublier qu'un pointeur nu n'est pas RAII, les ressources ne sont pas libérées à sa destruction.

  11. #11
    Membre expérimenté
    Homme Profil pro
    Chercheur
    Inscrit en
    Mars 2010
    Messages
    1 218
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Chercheur

    Informations forums :
    Inscription : Mars 2010
    Messages : 1 218
    Points : 1 685
    Points
    1 685
    Par défaut
    Si, lorsqu'il y a un delete dans un destructeur, tu penses qu'il y a violation du RAII, alors std::vector<int> viole RAII.
    RAII consiste justement à acquérir les ressources dans le constructeur (new) et à les libérer dans le destructeur (delete).
    C'est ce qu'implémente std::vector<int> et c'est pour cela que tu peux utiliser m_toto ainsi.
    Il y a une forme de transitivité : si toutes les données membres d'une classe respectent le RAII, alors elle le respecte aussi.
    Mais il ne faut pas oublier qu'il y a bien acquisition/libération de ressources pour chacun de ses membres, directement ou indirectement.

    La classe Foo est implémentée exactement sur le même modèle que std::vector<int>, c'est-à-dire sur le RAII.
    Tout est basé sur un mécanisme implicite du C++ : les destructeurs des objets sont appelés implicitement à la fin de leur vie.
    La ligne
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    { std::vector<int> m_vector; }
    appelle le destructeur de std::vector<int>, destructeur qui libère directement ou indirectement une ressource avec delete.

    La violation du RAII, c'est l'acquisition de ressources après l'initialisation,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    class Foo
    {
    public:
      void initialize(size_t size)
      { m_tab = new int[size]; }
      ~Foo()
      { delete []*m_tab; }
    private:
      int* m_tab;
    };
    ou la libération de ressources avant la destruction,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class Foo
    {
    public:
      Foo(size_t size)
      : m_tab(new int[size])
      {}
     
      void destroy()
      { delete [] m_tab; }
    private:
      int* m_tab;
    };
    ou la combinaison des deux :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class Foo
    {
    public:
      void initialize(size_t size)
      { m_tab = new int[size] };
     
      void destroy()
      { delete [] m_tab; }
    private:
      int* m_tab;
    };

  12. #12
    Membre chevronné Avatar de Ehonn
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    788
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2012
    Messages : 788
    Points : 2 160
    Points
    2 160
    Par défaut
    Citation Envoyé par Neckara Voir le message
    ne pas oublier qu'un pointeur nu n'est pas RAII
    Oui, mais encapsulé correctement dans une classe qui se charge de l'allocation et la désallocation elle-même donne une classe RAII.
    Après je suis d'accord pour dire que si le pointeur nu est inutile (quasiment « comme toujours »), il ne faut pas l'utiliser car c'est "compliqué" et dangereux.
    L'autre souci des pointeurs nus c'est qu'ils ont aucune sémantique (qui est responsable de l'objet ?).

  13. #13
    Membre expérimenté
    Homme Profil pro
    Chercheur
    Inscrit en
    Mars 2010
    Messages
    1 218
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Chercheur

    Informations forums :
    Inscription : Mars 2010
    Messages : 1 218
    Points : 1 685
    Points
    1 685
    Par défaut
    Bonjour Ehonn,

    et merci pour ta réponse.

    Citation Envoyé par Ehonn Voir le message
    Le RAII n'est pas violé si la classe qui encapsule un pointeur (ou autre) fait "la bonne chose".

    Pour moi le souci avec la première version est :
    - C'est "compliqué" car cela amène tous les souci de l'allocation dynamique
    - Si cela a du sens, il faudra retaper le constructeur par défaut, le constructeur de copie, l'opérateur d'affectation, ... (la règle des 5 + std::swap)
    (- Et je n'arrive pas à le compiler sans avoir une erreur d'utilisation de type incomplet avec new)
    Oui, c'est ce que je pense aussi.
    Dans la mesure du possible, et pour les mêmes raisons, j'évite comme toi de faire des allocations dynamiques.
    Je me demandais simplement s'il pouvait y avoir un véritable intérêt à privilégier les déclarations anticipées.
    Si par exemple quelqu'un privilégiait l'allocation statique des données membres jusqu'à être tombé sur un vrai problème, dans un gros projet par exemple.

    Pour la question du type incomplet, c'est normal.
    J'ai écrit un peu vite pour illustrer : il faut évidemment séparer déclarations et définitions pour que la déclaration anticipée soit possible.

  14. #14
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 012
    Points : 23 145
    Points
    23 145
    Par défaut
    @Aleph69 tu confonds le fait qu'une classe soit RAII et le fait que son utilisation puisse ne pas être RAII.

    Je ne dis pas que Foo n'est pas RAII mais que ton code n'est pas RAII à cause de l'utilisation de ton pointeur nu qui n'est ici pas utile.
    Ton pointeur nu n'est pas RAII alors qu'il pointe sur une instance RAII.

    C'est comme si tu encapsulait une instance RAII dans une classe non-RAII.

    Est-ce que vous comprenez l'idée/le problème ?

  15. #15
    Membre expérimenté
    Homme Profil pro
    Chercheur
    Inscrit en
    Mars 2010
    Messages
    1 218
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Chercheur

    Informations forums :
    Inscription : Mars 2010
    Messages : 1 218
    Points : 1 685
    Points
    1 685
    Par défaut
    Citation Envoyé par Neckara Voir le message
    Toto est RAII et pas dans le second cas.
    Je ne vois pas pourquoi ta classe Toto respecterait RAII et pas ma classe Foo : je ne vois pas de différence.

  16. #16
    Membre chevronné Avatar de Ehonn
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    788
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2012
    Messages : 788
    Points : 2 160
    Points
    2 160
    Par défaut
    Citation Envoyé par Aleph69 Voir le message
    Je me demandais s'il pouvait y a voir un véritable intérêt à privilégier les déclarations anticipées.
    - Pour les dépendances cycliques
    - Pour éviter l'explosion du temps de compilation

    Citation Envoyé par Aleph69 Voir le message
    Pour la question du type incomplet, c'est normal.
    J'ai écrit un peu vite pour illustrer : il faut évidemment séparer déclarations et définitions pour que la déclaration anticipée soit possible.
    C'était juste une remarque
    Personnellement : si possible, je n'aime pas séparer les deux et la déclaration anticipée m'oblige à le faire.

    Personnellement : je me soucierais du temps de compilation lorsque celui-ci explosera vraiment. Je préfère garder le code plus simple (et plus performant à l'exécution).

    La FAQ précise que les déclaration anticipées sont utiles lorsque on n'a pas besoin de connaître le vrai type. Ce qui n'est pas le cas ici.

  17. #17
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 012
    Points : 23 145
    Points
    23 145
    Par défaut
    Citation Envoyé par Aleph69 Voir le message
    Je ne vois pas pourquoi ta classe Toto respecterait RAII et pas ma classe Foo : je ne vois pas de différence.
    Je pense que tu as mal lu mon exemple.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #include "pleinsDeFichiers"
     
    class Server {
          public :
                Server(void){ // allocations }
                ~Server(void){ // désallocations }
    }
     
     
    int main(void)
    {
            Server s;
    }
    Puis-je vraiment dire que mon code respecte le principe RAII si sur mes 200 classes composant mon programme seul Server est RAII et que les autres classes que j'ai moi-même codé prennent un malin plaisir à mettre à mal le principe RAII ?

  18. #18
    Membre expérimenté
    Homme Profil pro
    Chercheur
    Inscrit en
    Mars 2010
    Messages
    1 218
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Chercheur

    Informations forums :
    Inscription : Mars 2010
    Messages : 1 218
    Points : 1 685
    Points
    1 685
    Par défaut
    Citation Envoyé par Neckara Voir le message
    @Aleph69 tu confonds le fait qu'une classe soit RAII et le fait que son utilisation puisse ne pas être RAII.

    Je ne dis pas que Foo n'est pas RAII mais que ton code n'est pas RAII à cause de l'utilisation de ton pointeur nu qui n'est ici pas utile.
    Ton pointeur nu n'est pas RAII alors qu'il pointe sur une instance RAII.

    C'est comme si tu encapsulait une instance RAII dans une classe non-RAII.

    Est-ce que vous comprenez l'idée/le problème ?
    Selon ta définition du RAII, une classe peut respecter le RAII (pas de new ou de delete) en ayant pour membre une instance de classe violant le RAII (new/delete dans construction/destruction).
    Il n'y a pas à distinguer classe RAII et utilisation RAII.
    Le RAII c'est l'acquisition de ressources à l'initialisation et la libération à la destruction : c'est un modèle de conception.
    Le fait d'avoir un pointeur nu pour donner membre ne viole pas RAII : la question est de savoir où la ressource est acquise et où elle est libérée, et uniquement cela.

  19. #19
    Membre expérimenté
    Homme Profil pro
    Chercheur
    Inscrit en
    Mars 2010
    Messages
    1 218
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Chercheur

    Informations forums :
    Inscription : Mars 2010
    Messages : 1 218
    Points : 1 685
    Points
    1 685
    Par défaut
    Citation Envoyé par Ehonn Voir le message
    - Pour les dépendances cycliques
    - Pour éviter l'explosion du temps de compilation


    C'était juste une remarque
    Personnellement : si possible, je n'aime pas séparer les deux et la déclaration anticipée m'oblige à le faire.

    Personnellement : je me soucierais du temps de compilation lorsque celui-ci explosera vraiment. Je préfère garder le code plus simple (et plus performant à l'exécution).

    La FAQ précise que les déclaration anticipées sont utiles lorsque on n'a pas besoin de connaître le vrai type. Ce qui n'est pas le cas ici.
    Merci Ehonn.
    Juste par curiosité : pourquoi tu n'aimes pas séparer déclarations et définitions?
    Moi je le fais systématiquement car j'aime bien avoir une vue d'ensemble de l'interface d'une classe sans me soucier forcément de l'implémentation.

  20. #20
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    La question ne devrait pas être "dois-je utiliser une déclaration anticipée", mais "dois-je utiliser un pointeur" ou encore "dois-je utiliser une référence"

    Quand on a répondu à ce problème plus important, on sait si on peut ou non faire une déclaration anticipée.

    Personnellement, j'ai la même politique pour la référence constante que la déclaration anticipée:
    Aussi souvent que possible, tant que cela a une sémantique valide.

    Je m'interdis d'introduire un pointeur/une référence pour le seul plaisir d'avoir une déclaration anticipée.
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

Discussions similaires

  1. Réponses: 2
    Dernier message: 23/05/2007, 14h05
  2. [TListBox] Selection par défaut
    Par Nuts07 dans le forum Composants VCL
    Réponses: 8
    Dernier message: 12/05/2003, 10h00
  3. Couleur de sélection par défaut
    Par sicard_51 dans le forum AWT/Swing
    Réponses: 2
    Dernier message: 20/04/2003, 23h35
  4. [SWING][FONT] choisir la police par défaut
    Par narmataru dans le forum AWT/Swing
    Réponses: 4
    Dernier message: 21/02/2003, 10h35
  5. Retour au mode texte par défaut
    Par coca dans le forum x86 16-bits
    Réponses: 6
    Dernier message: 12/12/2002, 17h22

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