шаблоны дизайна — идиома тела ручки в переполнении стека

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

//case1:
struct Impl1;
struct Handle1
{
// The definition will not be inline and will be defined in a C file
// Showing here for simplicity
void interface()
{
static_cast<Impl1*>(this)->interface();
}
}
struct Impl1 : public Handle1
{
void interface(){/*do Actual work*/}
private:
int _data;// and other private data
};

//case2:
struct Impl2
struct Handle2
{
//constructor/destructor to manage impl
void interface() // will not be inline as above.
{
_impl->interface();
}
private:
Impl2* _impl;
}

struct Impl2
{
void interface(){/*do Actual work*/}
private:
int _data;// and other private data
};

Дескриптор класса предназначен только для демонстрации функциональности. Они будут созданы и управляться только внутри библиотеки. Наследование предназначено только для абстрагирования деталей реализации. Не должно быть нескольких / разных классов impl. С точки зрения производительности, я думаю, что оба будут идентичны. Это? Я думаю о том, чтобы пойти с подходом case1. Есть ли какие-то вопросы, которые необходимо решить?

3

Решение

Ваш второй подход очень похож на брандмауэр компиляции
идиома (иногда известная как идиома pimpl). Единственная разница в том, что
в идиоме брандмауэра компиляции класс реализации обычно
(но не всегда) определяется как член. Не забывай конструктор
(который выделяет Impl) и деструктор (который освобождает его). Вместе
с конструктором копирования и оператором присваивания.

Первый подход также работает, но потребует заводских функций для
создавать объекты. Когда я использовал это, я просто сделал все
функции в Handle чисто виртуальный, и пусть клиентский код вызывает их
непосредственно. В этом случае, поскольку клиентский код на самом деле имеет указатели на ваш
объект (в идиоме брандмауэра компиляции, единственные указатели находятся в
Handle сам класс), клиенту придется беспокоиться о памяти
управление; если циклы невозможны, это один случай, когда
shared_ptr имеет много смысла. (Заводская функция может вернуть
shared_ptrНапример, и клиентский код может никогда не увидеть необработанный указатель.)

2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]