2010-06-29 3 views
1

Я хочу скрыть реализацию в файле реализации. Если объект не является общедоступным, я не хочу, чтобы заголовок объекта просачивался везде, где мой класс используется.Можно ли не включать переменную класса в заголовочный файл класса?

Предположим, я заголовок файла A.h для моего класса A:

Теперь, где бы я включил бы A.h, Foo.h также будут включены. Но я не могу использовать класс Foo вне класса A. Я бы предпочел не иметь эту линию #include "Foo.h". Есть ли способ переместить объявление переменной «foo» внутри реализации A.cpp?

Я подозреваю, что одно из возможных решений предполагает добавление слоя абстрактного класса (аналогия интерфейса). Это лучшее решение?

спасибо.

ответ

12

Используйте указатель на Foo и выделите его динамически, вместо использования объекта-члена. Тогда вам нужно включить Foo.h в A.cpp.

class Foo; 

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

+1, это идиома «PIMPL», и это стандартная практика. – greyfade

+0

+1 к ответу и +1 к greyfade для указания, что это в основном pimpl (непрозрачный указатель на частные детали реализации). – stinky472

+0

Ницца! Спасибо. Я помню, как я видел эту идиому, но в то время я не обращал на нее внимания. – Bear

1

Давид получил правильный ответ. Я буду ссылаться на эту статью для немного больше лечения на таком роде «непрозрачный указатель» трюк, как вы можете получить более сложными с ним, в зависимости от ваших потребностей:

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

Кроме того, это хорошее идея использовать типы shared_ptr для этой цели вместо необработанных указателей, подобных образцу. Это позаботится о том, чтобы очистить ресурсы для вас автоматически, как только последняя ссылка на Foo выходит за рамки.

+1

Я являюсь поклонником общих указателей, но я думаю, что в этом случае его избыток. Его обычно используют, когда владение сложно. Если foo используется только в объекте A, который его создает, нет проблем с владением. – KeithB

0

Да. Выберите ядовитый яд!

Вариант 1. Вперед декларация в интерфейсе.

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

Вариант 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(){...} 
}; 

Вариант 3. Частный частный. Это «скрытый», насколько общественность API выходит, что все, что имеет значение:

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

Вариант 4. Просто поместите объявление в «непубличных» namespace.ie, исключить его из документации и назовите его что-то отпугивать любопытных глаз:

namespace private_ { 
    class Foo { 
     ... 
    }; 
} 
class A { 
    private: 
     private_::Foo foo; 
    public: 
     do_stuff(); 
}; 
Смежные вопросы