Как друг ключевое слово (Класс/Функция) повреждает инкапсуляцию в C++?

Вы можете сделать это с помощью весов макета. Вес определяет, как разделить невостребованные части экрана. Дайте каждому EditText layout_width 0 и некоторый пропорциональный вес. То есть, дайте одному вес 2, а другому - 1, если вы хотите, чтобы первый занимал вдвое больше места.

18
задан 5 revs, 3 users 80%Chris 7 July 2009 в 18:38
поделиться

10 ответов

Цитата из C ++ FAQ который, я думаю, очень хорошо описывает ситуацию с другом и инкапсуляцией.

Нет! При правильном использовании они улучшают инкапсуляцию.

Часто бывает необходимо разделить класс пополам, когда две половины будут иметь разное количество экземпляров или разные времена жизни. В этих случаях, две половины обычно нуждаются в прямом доступ друг к другу (две половинки раньше учились в одном классе, так что вы не увеличил количество кода которому нужен прямой доступ к данным структура; ты просто перетасовал код на два класса вместо один). Самый безопасный способ реализовать это состоит в том, чтобы сделать две половинки друзьями друг друга.

Если вы используете друзей, как только что описано, вы сохраните личные вещи частный. Люди, которые не понимают это часто делает наивные попытки избежать использовать дружбу в таких ситуациях, как выше, и часто они на самом деле разрушить инкапсуляцию. Они либо используют публичные данные (гротеск!) или они делают данные доступны между половинками через public get () и set () член функции. Наличие общедоступного get () и set () для частного данные в порядке, только когда частный данные "имеют смысл" извне класс (с точки зрения пользователя). В во многих случаях член get () / set () функции почти так же плохи, как и публичные данные: они скрывают (только) имя частные данные, но они не скрывают существование частных данных.

25
ответ дан 30 November 2019 в 05:59
поделиться

Причина, по которой некоторые говорят, что «друзья» нарушают инкапсуляцию, заключается в том, что весь смысл инкапсуляции данных и функциональности заключается в том, что ничто другое, кому нужно видеть эти данные, не может, но друзья позволяют некоторым другим классам заглядывать внутрь.

Я лично думаю, что друзья не нарушают инкапускацию, потому что классы должны быть не полностью зависимыми, а скорее взаимозависимыми.

Возьмите аналогию с автомобилем. Обычно мы используем это как модель абстракции, говоря, что нам не нужно знать, как работает двигатель, чтобы знать, что нажатие на педаль газа заставляет его работать. В этом вся идея инкапсуляции, когда только функции, которые нам нужны для взаимодействия с классом, - единственные, о которых нам нужно знать.

Однако классу Механика определенно необходимо знать о конкретных внутренних механизмах автомобиля. , но нет смысла встраивать механика в машину.

Вот тут и приходят друзья. Вы делаете механика другом двигателя, тормозов или всего, что нужно починить, и он может это исправить. Он не может это исправить, если все, что он может сделать, это нажать на газ / тормоз.

17
ответ дан 30 November 2019 в 05:59
поделиться

Я публикую фрагмент из книги Страуструпа Дизайн и эволюция C ++ ,

2.10 Модель защиты, стр. 53.
[...]

Декларация о дружбе рассматривалась как механизм похож на один домен защиты, предоставляющий возможность чтения-записи в другой. Это является явной и конкретной частью объявление класса. Следовательно, я никогда не могли увидеть повторяющиеся утверждения, что друг объявление "нарушает инкапсуляцию" как угодно, только не сочетание незнание и путаница с не-C ++ терминология.

7
ответ дан 30 November 2019 в 05:59
поделиться

Дружба способствует сплоченности за счет некоторой инкапсуляции. У вас все еще есть инкапсулированный модуль (класс и его друзья), хотя он менее детализирован. Но когда альтернативой является добавление дополнительных функций к классу, которые не обязательно принадлежат классу, использование дружбы позволяет вам получить необходимый доступ, сохраняя при этом сплоченность класса. Инкапсуляция - не единственный и даже не самый важный принцип ООП.

0
ответ дан 30 November 2019 в 05:59
поделиться

Вы можете думать о C ++ как о очень примитивной системе управления доступом - либо вы можете получить доступ ко всем членам (друг или функция-член), либо вы можете получить доступ только к публичным членам (ко всему остальному, кроме .. .) или вы можете получить доступ к открытым и защищенным членам (... специальные правила для наследования).

«Инкапсуляция» в абстрактной форме также является примитивной системой управления доступом, за исключением того, что обычно мы говорим, что код, который является «частью class "является привилегированным и может манипулировать объектом всеми способами, которые позволяет язык. Код, который не является «частью класса», непривилегирован и должен использовать меньший, вероятно, опубликованный общедоступный интерфейс.

Итак, для чего нужен «друг»? Если вы так думаете, то это для написания привилегированного кода, который не является функцией-членом. Это необходимо, потому что есть некоторые вещи, которые по техническим причинам не могут быть функциями-членами. Я могу думать о перегрузках операторов, когда вам нужно преобразование в LHS, и о специализации стандартных функций шаблонов алгоритмов, таких как std :: swap (последнее является меньшей проблемой, поскольку если есть публичная функция подкачки, она маловероятно, что будет вреден и публичный метод подкачки. Но приятно поддерживать тех людей, которые хотят, чтобы интерфейсы были ортогональными).

Тогда возникает вопрос, нарушает ли инкапсуляцию, если привилегированный код не является членом функция? В Java вы, вероятно, сказали бы "да", поскольку код Java явно " называя каждый другой класс, который вы можете считать своим другом (например, сделать всех своих членов общедоступными или защитить пакет на Java, или сделать всех своих членов общедоступными на C ++). «друг» действительно должен работать с классами, а не только с методами, так что вы можете объявлять вложенные классы как друзья, где это необходимо, и иметь небольшие кластеры тесно связанных классов, которые не являются вложенными (то есть: рисовать границы инкапсуляция на более высоком уровне, чем у одного класса). Если вы используете его для плотного связывания всех ваших классов, то вы, вероятно, получите плохой код.

На самом деле это не из-за «друга», поскольку все, что я сделал, предоставило мне новый синтаксис для раскрытия членов, которые я мог бы в любом случае раскрыть как «общедоступные». Но если я выберу "друга" в качестве обходного пути, и использовать его, чтобы пробить мои собственные неадекватные общедоступные интерфейсы, тогда «друг», по сути, дал мне оправдание за плохой дизайн. В будущем я могу поклясться в этом и посоветовать другим поступить так же, но по той же причине я отказываюсь пить каждый раз, когда просыпаюсь с похмелья. Другие могут быть мудрыми или достаточно удачливыми, чтобы пользоваться преимуществами без серьезных побочных эффектов.

Таким образом, «друг» сам по себе допускает нарушение инкапсуляции, как это делает арифметика указателей, и точно так же, как алкоголь позволяет упасть в канаву 3 часа ночи. Однако с осторожностью и приличным дизайном конкретные применения друга не должны и не должны нарушать инкапсуляцию. И, на случай, если это прочитают какие-либо потенциальные будущие работодатели, когда я пью, я обычно не страдаю похмельем; -)

В конечном итоге проблема в том, что на каждом языке, который я знаю, интерфейсы ведут себя как наследование в том смысле, что открытый интерфейс класса включает в себя все члены всех интерфейсов, которые он реализует. Таким образом, интерфейс класса больше , чем любой другой. В этом нет ничего плохого, поскольку отношения «есть-а» являются ключевыми для объектно-ориентированного подхода. Кроме того, это хорошо соответствует тому, что происходит, когда вы публикуете интерфейс, то есть любой клиент может его использовать. Это просто естественно не соответствует тому, что требуется во многих проектах, а именно, чтобы классы по умолчанию имели маленький интерфейс, но также предлагали больший интерфейс для «суперпользователей» . Поэтому вместо этого по умолчанию используется большой интерфейс, а «субпользователи» придерживаются скучных частей.

Итак, friend - это один грубый инструмент, предлагающий более крупный интерфейс «суперпользователям». не затрагивая "субпользовательский" интерфейс. Однако, поскольку это настолько прямолинейно, это действительно работает только тогда, когда все соответствующие классы спроектированы вместе, и аргументы о том, какими должны быть связанные классы, приводят к разногласиям относительно того, что «нарушает инкапсуляцию». Помните, что уровни доступа в языках не должны обеспечивать инкапсуляцию, а C ++, в частности, является языком с несколькими парадигмами. Итак, C ++ прилагает некоторые усилия, чтобы помочь программистам в обеспечении инкапсуляции, но программист все равно должен хорошо проектировать и использовать доступные функции в соответствии со своими собственными принципами программирования.

а споры о том, какими должны быть связанные классы, приводят к разногласиям относительно того, что «нарушает инкапсуляцию». Помните, что уровни доступа в языках не должны обеспечивать инкапсуляцию, а C ++, в частности, является языком с несколькими парадигмами. Итак, C ++ прилагает некоторые усилия, чтобы помочь программистам в обеспечении инкапсуляции, но программист все равно должен хорошо проектировать и использовать доступные функции в соответствии со своими собственными принципами программирования.

а споры о том, какими должны быть связанные классы, приводят к разногласиям относительно того, что «нарушает инкапсуляцию». Помните, что уровни доступа в языках не должны обеспечивать инкапсуляцию, а C ++, в частности, является языком с несколькими парадигмами. Итак, C ++ прилагает некоторые усилия, чтобы помочь программистам в обеспечении инкапсуляции, но программист все еще должен хорошо проектировать и использовать доступные функции в соответствии со своими собственными принципами программирования.

3
ответ дан 30 November 2019 в 05:59
поделиться

Encapsulation means that you can't see what's inside, and friend means that you can see inside. Depending on your point of view, friend therefore either breaks encapsulation (by letting the friend see inside), or extends it (by letting the developer relax the barrier to specific friends only).

FWIW, a good rule of thumb is to say that only nested/inner classes should be declared as friends; this rule can be summarized as "no long-distance friends", i.e. a class's friends (if any) should be declared within the same header file as the class itself.

9
ответ дан 30 November 2019 в 05:59
поделиться

You have two different schools of thought.

The first one (Java & C# ...) :: throw every function in the public area of the class, whether that function 'needs' to access the 'private' area or not.

The second one (C++ ...) :: provide 'only' the needed functions so this class can survive, and provide higher level functions in unrelated collection of the created type.

IMHO :: C++ satisfies OOP goals clearly.

3
ответ дан 30 November 2019 в 05:59
поделиться

As soon as you declare a friend function, access specifiers, and thus, encapsulated details of your class will become accessible by that friend function, which is not a part/method of your class. So, you basically delegate some control over internal data structures and methods to an external function that you 'trust'

0
ответ дан 30 November 2019 в 05:59
поделиться

The friend keyword allows other classes to access private and protected data members in C++. Some people think this is breaking encapsulation, other people think that it's extending encapsulation to a small number of outside classes that need access to private/protected data. The "breaking encapsulation" means that members and methods are usually private for a reason, and the friend keyword breaks that encapsulation.

In the code I've seen the friend keyword usually breaks encapsulation and reduces code quality, but there are occasionally situations in which it's used well.

Here's a simple tutorial on class friendship and inheritance if you've never seen it before:

Friendship and Inheritance

0
ответ дан 30 November 2019 в 05:59
поделиться

If you draw a line around everyone who can access private data, that is the extent that the data is encapsulated.

If you use the friend keyword, that line has to be drawn around more things. Thus encapsulation is extended or broken, depending on your point of view.

In general, I discourage the use of friend. Instead consider adding accessors for private data.

-2
ответ дан 30 November 2019 в 05:59
поделиться
Другие вопросы по тегам:

Похожие вопросы: