С++, действительно ли частные функции действительно должны быть в файле заголовка?
Я всегда думал о заголовочных файлах как о "публичном интерфейсе", описывающем класс, и в этом случае было бы лучше сохранить частные поля и функции в файле cpp.
Я понимаю, что закрытые поля должны быть в заголовке, чтобы другие классы могли определить, сколько памяти будет занимать экземпляр класса, но мне пришло в голову, когда я собирался написать приватную вспомогательную функцию, что эту функцию можно сделать static, в этом случае ему вообще не нужно быть "частью класса", с такой же легкостью это может быть обычная функция в файле.cpp определения класса.
Затем мне пришло в голову, что все частные функции потенциально могут быть переписаны, чтобы быть статичными, принимая указатели/ссылки на поля класса вместо ожидания определения в классе.
Это избавит от необходимости объявлять любые частные функции в заголовочном файле.
Мне нравится следовать соглашениям, поэтому теперь я хочу спросить, считается ли это установленным соглашением в C++, что нестатические частные функции должны быть в заголовочном файле? Как насчет статических функций или статических констант?
РЕДАКТИРОВАТЬ: Я собираюсь вставить некоторый код, чтобы объяснить, что я получаю:
.h файл:
#ifndef SOME_CLASS_H
#define SOME_CLASS_H
class SomeClass
{
private:
int x;
public:
void combineWithX(int y);
};
#endif
файл.cpp
#include "SomeClass.h"
void someHelper(int* x)
{
*x = (*x) + 1;
}
void SomeClass::combineWithX(int y)
{
someHelper(&x);
x += y;
}
Обратите внимание, что someHelper(int* x)
в файле cpp ссылается на закрытый элемент x по духу, но не напрямую, и, следовательно, не должен появляться в заголовке. Мне интересно, считается ли такая вещь "плохим стилем"?
Ответы
Ответ 1
Я согласен с тем, что проблема заключается в том, что детали реализации должны быть представлены в файле заголовка; он мешает разделению интерфейса и реализации.
Перемещение функций private helper, которые будут свободными функциями в файле .cpp
(я полагаю, это то, что вы подразумеваете под "static" ), не будет работать, если эти функции должны получить доступ к частным переменным-членам.
Вам может быть интересно посмотреть идиому pImpl (подробнее)
Ответ 2
Простая идиома нужна только
- если вам нужно вывести "переменные" закрытого члена из публичного заголовка (для поддержания бинарной совместимости новых выпусков - если вы не знаете, что это значит, это, вероятно, не является проблемой)
- Если этот дизайн облегчает понимание
Если вы хотите только удалить закрытые функции-члены из открытого заголовка, достаточно использовать внутренний класс. Это не имеет штраф за перенаправление как идиома PImpl.
публичный.h файл
#ifndef SOME_CLASS_H
#define SOME_CLASS_H
class SomeClass
{
private:
struct Private;
int x;
public:
void combineWithX(int y);
};
#endif
в.cpp файле
#include "SomeClass.h"
/** Declare all private member functions of SomeClass here
This class can access not only private members of SomeClass
but also friends of SomeClass. */
struct SomeClass::Private
{
static void someHelper(SomeClass& self)
{
self.x = self.x + 1;
}
};
void SomeClass::combineWithX(int y)
{
Private::someHelper(*this);
x += y;
}
SomeClass::Private
может иметь любое количество вспомогательных функций, которые имеют полный доступ ко всем private/друзьям SomeClass
, без необходимости объявлять какие-либо из них в заголовочном файле.