1 votes

Est-il possible de ne pas inclure une variable de classe dans un fichier d'en-tête de classe ?

Je veux cacher une implémentation dans le fichier d'implémentation. Si l'objet n'est pas public, je ne veux pas que l'en-tête de l'objet fuit partout où ma classe est utilisée.

Supposons que j'ai un fichier d'en-tête A.h pour ma classe A :

#include "Foo.h"

class A{
    private:
        Foo foo;
    public:
        do_stuff();
};

Maintenant, partout où je voudrais inclure A.h , Foo.h seraient également inclus. Mais je n'ai aucune utilité pour la classe Foo n'importe où en dehors de la classe A . Je préfère ne pas avoir cela #include "Foo.h" ligne. Existe-t-il un moyen de déplacer la déclaration de la variable 'foo' à l'intérieur de l'implémentation ? A.cpp ?

Je soupçonne qu'une solution possible consiste à ajouter une couche de classe abstraite (analogie avec une interface). Est-ce la meilleure solution ?

Merci.

12voto

David Points 3766

Utilisez un pointeur vers Foo et allouez-le dynamiquement, plutôt que d'utiliser un objet membre. Il vous suffit alors d'inclure Foo.h dans A.cpp.

class Foo;

class A{
    private:
        Foo* foo;
    public:
        do_stuff();
}

1voto

holtavolt Points 2798

David a la bonne réponse. Je me référerai à cet article pour un traitement un peu plus poussé de ce genre d'astuce de "pointeur opaque", car vous pouvez être plus élaboré avec, en fonction de vos besoins :

http://en.wikipedia.org/wiki/Opaque_pointer

De plus, c'est une bonne idée d'utiliser des types shared_ptr à cette fin au lieu de pointeurs bruts comme dans l'exemple. Cela prendra soin de nettoyer les ressources pour vous automatiquement, une fois que la dernière référence à Foo sera sortie de la portée.

0voto

John Points 67

Oui. Choisissez votre poison !

Option 1. Transférer la déclaration dans l'interface.

class A {
    private:
        class Foo;
        Foo* foo;
};

Option 2. ABC.

// A.hpp
class A {
    public: virtual void do_stuff() = 0;
};

// A.cpp
class A_impl : public A {
   class Foo { /*etc*/ };
   Foo foo;
   void do_stuff (){...}
};

Option 3. Privé est privé. Il est "caché" en ce qui concerne l'API publique, ce qui est tout ce qui compte :

class A {
    private:
        class Foo {
            ...
        };
        private_::Foo foo;
    public:
        do_stuff();
};

Option 4. Il suffit de placer la déclaration dans un espace de noms "non public", c'est-à-dire de l'omettre de la documentation et de lui donner un nom qui effraie les regards indiscrets :

namespace private_ {
   class Foo {
      ...
   };
}
class A {
    private:
        private_::Foo foo;
    public:
        do_stuff();
};

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X