Перейти к содержанию

Непрозрачный указатель

Материал из Википедии — свободной энциклопедии
(перенаправлено с «Pimpl»)

Непрозрачный указатель (англ. 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 и большинстве диалектов Паскаля клиентский код перекомпилируется при любых изменениях в исходном тексте библиотеки, даже если бинарная совместимость сохранена. А хранение модуля как бинарного файла не даёт предупреждениям библиотеки проникать в клиентский код.

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

Примечания

[править | править код]
  1. ↑ Клеменс, 2015, Непрозрачный указатель, с. 359.
  2. ↑ Смит, 2013, Порождающий шаблон, с. 121.
  3. ↑ Клеменс, 2015, Мирное сосуществование, с. 127.
  4. 1 2 Chris McKillop. Programming Tools — Opaque Pointers. QNX Software Systems. Дата обращения: 16 января 2019. Архивировано из оригинала 12 ноября 2021 года.