Избегание объявления частных функций в заголовочных файлах классов (С++)
(В С++) У меня есть класс, структура которого объявлена в файле заголовка. Этот заголовочный файл включен во множество исходных файлов, так что когда я его редактирую, мне нужно перекомпилировать множество файлов.
Класс имеет набор частных функций, которые вызывается только в одном исходном файле. В настоящее время они объявляются в структуре класса в файле заголовка. Когда я добавляю новую функцию этого типа или редактирую аргументы, это приводит к перекомпиляции большого количества файлов. Я хотел бы объявить функции где-то еще, так что только файл, который определяет и вызывает их, перекомпилируется (чтобы сэкономить время). Тем не менее, они все равно должны иметь доступ к внутренним переменным класса.
Как я могу это достичь?
Ответы
Ответ 1
Невозможно объявить функции-члены класса вне объявления основного класса. Итак, если вы хотите объявить за пределами рассматриваемого класса функции, которые могут обращаться к переменным-членам определенного экземпляра класса, тогда я не вижу альтернативы, кроме как передать этот экземпляр функции. Кроме того, если вы хотите, чтобы функции имели доступ к закрытым и защищенным переменным, вам нужно будет поместить их в новый класс и сделать из него оригинальный класс. Например.
header.h:
class FooImpl;
class Foo {
public:
int bar();
friend class FooImpl;
private:
int var;
}
impl.cpp:
#include "header.h"
class FooImpl {
public:
int bar(Foo &);
}
int FooImpl::bar(Foo &foo) {
return foo.var;
}
int Foo::bar() {
return FooImpl::bar(*this);
}
Ответ 2
Используйте pImpl idiom - Ваш видимый класс хранит указатель на реальный класс и переадресации вызовов на публичные функции-члены.
РЕДАКТИРОВАТЬ: В ответ на комментарии
// Foo.h:
class FooImpl; // Do *not* include FooImpl.h
class Foo {
public:
Foo();
~Foo();
//.. also need copy ctor and op=
int bar();
private:
FooImpl * Impl;
};
// FooImpl.h:
class FooImpl {
public:
int bar() { return Bar; }
private:
int Bar;
};
// Foo.cpp:
#include "FooImpl.h"
Foo::Foo() { Impl = new FooImpl(); }
Foo::~Foo() { delete Impl; }
int Foo::bar() { return Impl->bar(); }
Сохранение фактической реализации вашего класса в FooImpl
- Foo
должно иметь копии публичных членов FooImpl
и просто переадресовывать вызовы на них. Все пользователи будут включать только "Foo.h" - вы можете изменить все личные данные FooImpl
, если пользователи Foo
не видят никаких изменений.
Ответ 3
Вы ищете Брандмауэр компилятора, a.k.a. PIMPL?
Ответ 4
Создайте абстрактный базовый класс, который содержит только публичные функции и ссылается на это в ваших заголовках. Создайте свой настоящий класс как реализацию где-то еще. Только исходные файлы, которые должны создавать ваш класс, должны видеть заголовок класса реализации.