Является ли решение возврата необработанного указателя на Bar предпочтительным вариантом?
Это решение и не обязательно плохое.Возвращение ссылки было бы предпочтительным в тех случаях, когда объект всегда существует (не в этом случае, поскольку конструктор по умолчанию Foo
не создает Bar
).
Некоторые программисты предпочитают использовать оболочку дляголые указатели (такие как observer_ptr
, который был предложен в стандарте), чтобы отличать его от указателя, целью которого является итерация массива, или от обладания голыми указателями (последних следует избегать).
У меня такое чувство, что это тормозит инкапсуляцию
Вся ваша предпосылка - нарушить инкапсуляцию, поскольку вы хотите "изменить внутренние объекты" .Если вы хотите избежать разрушения инкапсуляции, вам, возможно, потребуется еще больше изменить дизайн, чтобы вам не нужно было изменять внутренние объекты (внешне).
Решение, которое не нарушает инкапсуляцию, заключается впредоставить конкретный интерфейс для Foo
для модификации, такой как:
void Foo::transmogrify_bar(int gadgets) {
bar->transmofgrify(gadgets);
}
Полезна ли эта инкапсуляция для вашего API, это другой вопрос.В некоторых случаях это важно, в других это не имеет большого значения.
, если Bar будет храниться в контейнере в Foo.Вернул бы я указатель на весь контейнер, итератор для контейнера ...?
Хотели бы вы, чтобы клиент мог изменять контейнер (добавлять, удалять элементы)?
Это еще больше нарушает инкапсуляцию.Вместо этого у вас могут быть итераторы begin
и end
, которые не позволяют изменять сам контейнер, что приводит к эквивалентной инкапсуляции возврата указателя в случае одного объекта.
Вы можетепредоставьте только константные итераторы и добавьте итератор в качестве аргумента в transmogrify
, чтобы сохранить инкапсуляцию изменения Bar
.
Наконец, для полной инкапсуляции вам потребуется использовать шаблон PIMPL, чтобы полностью скрыть Bar
.