У меня есть некоторый код на C, который использует неполные структуры таким образом (упрощенный пример):
something.h
struct something;
struct something *new_something();
int work_a(struct something *something);
int work_b(struct something *something, const char *str);
void free_something(struct something *something);
somecode.c
int some_function()
{
struct something *something;
int x;
something = new_something();
x = work_a(something);
free_something(something);
return x;
}
Я думал, я в основном делаю C ++ здесь, почему бы не попробовать написать это на C ++.
Вопрос (я новичок в C ++), как мне добиться того же в C ++? Если я пытаюсь добавить объявление функции-члена неполного класса, я получаю
error: incomplete type 'something' named in nested name specifier
из лязга Если написать полный класс в заголовке, это приведет к потере всей цели сокрытия данных, а изменение закрытых переменных в классе приведет к перекомпиляции каждого файла, включая «thing.h », что, как мне кажется, здесь не нужно. Мне не нужны файлы, использующие «thing.h «, чтобы знать размер этой структуры / класса, обычно у меня достаточно указателя. Я подозревал, что это должно выглядеть так:
class Something;
Something::Something();
Something::~Something();
int Something::work_a(int x);
таким образом, я мог написать то же самое, что и в Си, только короче и даже чище. Любой C ++-кодер, желающий просветить этого смертельного C-кодера?
Посмотрите на эту статью: Скрытие деталей реализации в C ++. Он должен указать вам направление, в котором вы смотрите. Обратите внимание, что наследование используется для достижения цели. Также следует понимать, что в C ++ структура — это класс, все члены которого имеют открытый доступ (включая функции, конструкторы и деструкторы). Как минимум, интерфейс должен быть объявлен как класс, а затем наследоваться от него публично в скрытой реализации класса внутри файла cpp (а не другого заголовочного файла).
На шаблоне проектирования Pimpl, проверьте эту статью переполнения стека: шаблон pimpl против конструкции моста. Это также должно помочь.
Одним из способов достижения этого является использование шаблона проектирования Pimpl, в котором у вас есть указатель на некоторую приватную структуру / класс, о которой знает только ваша реализация. Ваши частные функции используют указатель, и теоретически он может быть в основном встроенным.
Когда вы выделяете память новым оператором, компилятор должен знать, сколько места для данных выделить. Размер данных Something был обнаружен компилятором, прежде чем вы сможете использовать new для создания экземпляра Something.
Используйте что-то подобное в Something.h
class Something {
public:
Something();
private:
struct HiddenData;
HiddenData* m_pHidden;
};
Используйте что-то подобное в Something.cpp
struct Something::HiddenData {
int a;
int b;
};
Something::Something() : m_pHidden(new HiddenData()) {
m_pHidden->a = 1;
}