Непрозрачный указатель
Непрозрачный указатель (англ. opaque pointer) — идиома программирования, когда для прикладного программиста объект представляет собой указатель на данные неизвестного устройства. Программист не вправе разыменовывать этот указатель, однако может передавать его в функции, которые знают, как работать с объектом[1].
Данная идиома была реализована в языках программирования C, Objective C, COBOL и C++. Она известна также под названиями указатель на реализацию (pimpl), дескриптор (handle), d-указатель и «чеширский кот»[2]. В языке программирования C непрозрачные указатели используются для создания интерфейса между структурами данных языка C и теми языками программирования, которые не имеют методов обращения к ним[3].
От языка к языку непрозрачный указатель может быть указателем общего вида void*/Pointer, указателем на недоопределённый тип, указателем на пустой кортеж, или (если указателей в языке нет) целым типом. Или, как часто бывает в Си++, обёрткой вокруг этих типов.
Выгоды
[править | править код]- Сохранение бинарной совместимости со временем[4]
- Меняющийся размер объекта и раскладка полей в нём видны только библиотеке. Эту информацию можно выяснить только хакерством, чтобы программист клиентской части не закладывался на нестабильные части объекта. Правомерно клиентский код может оперировать лишь указателем, чей объём — свойственные платформе 4 или 8 байт. Потому идиома любима системными библиотеками, независимо от языка.
- Простота написания обёрток для других языков программирования
- Указатель — это очень простой тип. А если в языке-клиенте указателей нет, вместо него можно взять целый тип подходящей длины. Если язык-клиент имеет собственные механизмы управления жизнью объекта (как конструктор, деструктор, копирование и перемещение в Си++), обёртка своими силами пишет такое управление.
- Ускорение компиляции в Си/++
- В этих языках есть специфичная причина: в заголовочном файле *.h описаны зависимости, нужные клиентскому коду, а в *.cpp-модуле — внутренние. Если объект имеет простой интерфейс, но сложное внутреннее устройство, в заголовочный файл неизбежно попадут внутренние подобъекты[4]. Это удлиняет компиляцию, перекомпилирует клиентский код при внутренних изменениях в библиотеке, даёт риск конфликта модулей, а если во внутреннем заголовке предупреждение компилятора — оно будет растиражировано по всей программе. Идиома pimpl переносит всё, что не входит во внеший интерфейс, в CPP-файл, ограничивая эти негативные явления «внутренностями» библиотеки.
- Для сравнения: в Java и большинстве диалектов Паскаля клиентский код перекомпилируется при любых изменениях в исходном тексте библиотеки, даже если бинарная совместимость сохранена. А хранение модуля как бинарного файла не даёт предупреждениям библиотеки проникать в клиентский код.
Недостатками являются обязательное выделение динамической памяти при создании объекта и возвращение при разрушении, лишняя машинная команда в определённых операциях, а также многословность.
Примечания
[править | править код]- ↑ Клеменс, 2015, Непрозрачный указатель, с. 359.
- ↑ Смит, 2013, Порождающий шаблон, с. 121.
- ↑ Клеменс, 2015, Мирное сосуществование, с. 127.
- 1 2 Chris McKillop. Programming Tools — Opaque Pointers. QNX Software Systems. Дата обращения: 16 января 2019. Архивировано из оригинала 12 ноября 2021 года.
Источники
[править | править код]- Бен Клеменс. Язык С в XXI веке. — М. : ДМК, 2015. — 376 с. — ББК 32.973.26. — УДК 004.6(G). — ISBN 978-5-97060-101-3.
- Джейсон Мак-Колм Смит. Элементарные шаблоны проектирования. — М. : И. Д. Вильямс, 2013. — 304 с. — ББК 32.973.26-018.2.75. — УДК 681.3.07(G). — ISBN 978-5-8459-1818-5.