Во-первых, давайте посмотрим на это утверждение в контексте:
Согласно действующему C ++ (пункт 28),
"избегать возврата дескрипторов (ссылки,
указатели или итераторы) на объект
Внутренности. Это увеличивает инкапсуляцию,
помогает константным функциям-членам действовать
const, и сводит к минимуму создание
свисающие ручки. "
Это в основном говорит о способности класса поддерживать инварианты (грубо говоря, свойства, которые остаются неизменными).
Допустим, у вас есть оболочка для виджета кнопки, Button , которая хранит дескриптор окна, специфичный для ОС, для кнопки. Если бы клиент, использующий класс, имел доступ к внутреннему дескриптору, он мог вмешаться в него, используя вызовы, специфичные для ОС, такие как уничтожение кнопки, ее невидимость и т. Д. По сути, возвращая этот дескриптор, ваши Button жертвы класса любой контроль, который изначально имел над ручкой кнопки.
Вы хотите избежать подобных ситуаций в таком классе Button, предоставляя все, что вы можете сделать с кнопкой в качестве методов этого класса Button. Тогда вам больше не нужно возвращать дескриптор к дескриптору кнопки, специфичной для ОС.
К сожалению, это не всегда работает на практике. Иногда вам приходится возвращать дескриптор или указатель или какой-либо другой внутренний элемент по ссылке по разным причинам. Давайте возьмем boost :: scoped_ptr , например. Это интеллектуальный указатель, предназначенный для управления памятью через внутренний указатель, который он хранит. У него есть метод get (), который возвращает этот внутренний указатель. К сожалению, это позволяет клиентам делать такие вещи, как:
delete my_scoped_ptr.get(); // wrong
Тем не менее, этот компромисс был необходим, потому что во многих случаях мы работаем с API-интерфейсами C / C ++, требующими передачи обычных указателей. Компромиссы часто необходимы для удовлетворения библиотек, которые не принимают ваш конкретный класс, но принимают один из его внутренних органов.
В вашем случае попробуйте подумать, может ли ваш класс избежать возврата внутренних объектов таким образом, вместо этого предоставляя функции для выполнения всего, что вы хотели бы сделать с внутренним интерфейсом через ваш публичный интерфейс. Если нет, то вы сделали все, что могли; вам придется возвращать указатель / ссылку на него, но было бы хорошей привычкой документировать его как особый случай. Вам также следует подумать об использовании друзей, если вы знаете, в каких местах необходимо заранее получить доступ к внутренним материалам класса; таким образом, вы можете сохранить такие методы доступа закрытыми и недоступными для всех остальных.
Возвращение объектов по значению является единственным
как я могу думать, чтобы избежать возвращения
ручки. Это для меня предполагает, что я должен
вернуть закрытый объект
цените как можно больше.
Нет, если вы можете вернуть копию, то вы можете в равной степени вернуться по константной ссылке. Клиенты не могут (при нормальных обстоятельствах) вмешиваться в такие внутренние процессы.