Иногда разработчику класса нужно скрыть от пользователя некоторые особенности реализации интерфейса. Речь идет о секции private, в которой обычно размещаются переменные класса и методы, предназначенные сугубо для внутреннего использования. Пользователю вовсе необязательно видеть секцию private, особенно, если реализация класса находится внутри скомпилированной библиотеки .dll, а в руках пользователя лишь заголовочный файл.
Читать далее...Предполжим, есть заголовочный файл следующего вида.
//------------------------------------------------------------ class A { public: A(char *, int); ~A(); private: int m_Value; char *m_Str; static int g_Instances; void init(); }; //------------------------------------------------------------
|
и файл с реализацией класса:
//------------------------------------------------------------ int A::g_Instances=0; A::A(char *Str, int Val) { m_Value=Val; m_Str=Str; init(); } void A::~A() {} void A::init() { g_Instances++; } //------------------------------------------------------------
|
Существует достаточно простое решение для минимизации содержимого секции private (до двух строчек).
Заголовочный файл оформляется следующим образом:
//------------------------------------------------------------ class A { public: A(char *, int); ~A(); private: class InternalData; InternalData *m_IData; }; //------------------------------------------------------------
|
Вот и всё. Объявляется новый класс, и создается переменная-указатель. Для ее создания компилятору не нужна реализация класса InternalData.
Теперь как же выглядит файл с реализациями классов A и InternalData? Во-первых, добавилось тело класса InternalData, и, во-вторых, доступ к полям private осуществляется через m_IData.
//------------------------------------------------------------ class A::InternalData { public: int m_Value; char *m_Str; static int g_Instances; void init() { g_Instances++; } }; int A::InternalData::g_Instances=0; A::A(char *Str, int Val) { m_IData=new InternalData(); m_IData->m_Value=Val; m_IData->m_Str=Str; m_IData->init(); } void A::~A() { delete m_IData; } //------------------------------------------------------------
|