В чем смысл класса С++ Wrapper?
У меня есть небольшая проблема в понимании класса-оболочки. Было бы здорово, если бы кто-то мог помочь предоставить примерные примеры.
- Что такое класс С++ Wrapper и каковы обстоятельства его написания?
- Что он использует?
Спасибо.
Ответы
Ответ 1
"класс-оболочка" - это де-факто термин, означающий класс, который "обертывает" ресурс; то есть управляющий ресурсом. Когда люди пишут обертку, тогда они делают что-то вроде этого:
class int_ptr_wrapper
{
public:
int_ptr_wrapper(int value = 0) :
mInt(new int(value))
{}
// note! needs copy-constructor and copy-assignment operator!
~int_ptr_wrapper()
{
delete mInt;
}
private:
int* mInt;
};
Этот класс управляет ( "wraps" ) указателем на int
. Все ресурсы должны быть обернуты каким-то образом, для чистоты (без явного очищения кода или шума) и правильности (деструктор гарантированно работает, не может забыть очистить и безопасно с исключениями).
Этот шаблон называется облачным управлением ресурсами (SBRM), хотя гораздо более распространенное (но наиболее эзотерическое) имя - это инициализация ресурсов (RAII). Идея состоит в том, чтобы связать очистку ресурса с деструктором по причинам, указанным выше: область действия обрабатывает остальные.
Обратите внимание, что я сказал, что отсутствует экземпляр-конструктор и оператор присваивания копии. Это связано с Правилом трех. (См. Связанный вопрос для подробного объяснения.) Самый простой способ правильно реализовать это правило - с помощью идиомы copy-and-swap, объясненной здесь.
Иногда, это не прагматично писать класс-оболочку для очистки ресурсов, обычно, когда ресурс уникален или используется один раз. (Или с транзакционным программированием.) Решение этого называется защитой области, способ записи кода очистки внутри функции, которая ему нужна.
Вы можете найти дополнительную информацию, выполнив поиск в своем любимом поисковом устройстве (то есть Google) или перейдя в "основной" документ здесь. Обратите внимание, что Boost предоставляет утилиту для этого, как это обычно делается для хороших идиом.
Ответ 2
Обертка - это всего лишь небольшой класс, целью которого является предоставление другого интерфейса, чем тот, который он обертывает. Например, принято использовать C API и писать один или несколько классов, которые "обертывают" его, чтобы обеспечить объектно-ориентированный интерфейс, а не процедурный.
Ответ 3
Вы спросили об обстоятельствах написания классов-оболочек. Например, если вы работаете в компании, которая использует различные типы камер, скажем USB, firewire и т.д. Каждый из производителей предоставит другой набор функций через API для запуска камеры, установки параметров и чтения потока изображений из него.
Теперь программист, который создает приложения в вашей компании, должен быть изолирован от всех конкретных деталей в различных API. Теперь, что вы можете сделать, это написать класс оболочки вокруг API для каждой из камер или умнее, только один класс с простыми функциями, обертывая существующий код, предоставляемый API.
Например, мы можем создавать классы
MyUSBCameraWrapperClass,
MyFirewireCameraWrapperClass
с некоторыми функциями-членами, такими как
setFrameRate (int fps),
getImgFrame (* framebuffer) и т.д.
Затем программисты в вашей компании могут использовать MyUSBCameraWrapperClass usbcam; usbcam.setFrameRate(30) и т.д. Вы понимаете?
Ответ 4
Класс-оболочка - это класс, который обертывает функциональность другим интерфейсом.
Предположим, что у вас есть функция f()
:
void f() { std::cout << "hello\n"; }
Простой класс-оболочка может быть
class C {
f() { std::cout << "hello\n"; }
};
Вы можете написать оболочку, когда ваша существующая база кода ожидает определенный интерфейс. В этом и заключается суть шаблона проектирования адаптера. Или вы можете обернуть функцию в класс, если хотите сохранить состояние для этой функции. Или вы можете обернуть функцию в конструкторе класса или деструкторе, если вы хотите, чтобы он удобно и автоматически вызывался для вас правильным и детерминированным образом. И этот список продолжается.
Ответ 5
Я использую два вида:
-
оболочки ресурсов для пар функций, предоставляемых ОС, например
- UNIX: открыть/закрыть, mmap/munmap, dlopen/dlclose
- Windows: CreateFile/DestroyHandle, CreateFileMapping/CloseHandle, LoadLibrary/FreeLibrary.
-
функциональные оболочки для функций, предоставляемых ОС, например
- UNIX: запись, чтение, dlsym
- Windows: ReadFile, WriteFile, GetProcAddress
Обертка ресурсов делает уверенным, что код, сгенерированный компилятором, беспокоится об уничтожении ресурса, созданного конструктором, через то, что сегодня называется RAII. Легко сочетать такие классы через отношения базового/членского класса в сложные классы.
В случае сбоя функции создания генерируется исключение системной ошибки, предоставляющее богатую информацию об ошибке об ошибке.
Функциональная оболочка используется вместо простой функции ОС. Также в случае сбоя создается системное исключение.
Таким образом, кому-то, использующему мой код, не нужен отладчик и код отладки, чтобы выяснить, что происходит в сложной среде со многими библиотеками и процессами и удаленными машинами.
Кроме того, эти обертки предоставляют некоторую абстракцию ОС - при использовании кода их не нужно беспокоиться о различиях ОС.