edit: Чтение faq немного дольше. Мне нравится идея перегрузки и добавления оператора << >> как друга этих классов, однако я не уверен, как это не нарушает инкапсуляцию
Как бы это нарушило инкапсуляцию?
Вы нарушаете инкапсуляцию, когда разрешаете неограниченный доступ к элементу данных. Рассмотрим следующие классы:
class c1 {
public:
int x;
};
class c2 {
public:
int foo();
private:
int x;
};
class c3 {
friend int foo();
private:
int x;
};
c1
является очевидно не инкапсулированным. Любой может прочитать и изменить x
в нем. У нас нет способа обеспечить какой-либо контроль доступа.
c2
явно заключен в капсулу. Нет общего доступа к x
. Все, что вы можете сделать, это вызвать функцию foo
, которая выполняет некоторую значимую операцию над классом .
c3
? Это менее инкапсулировано? Разрешает ли он неограниченный доступ к x
? Разрешает ли доступ к неизвестным функциям?
Нет. Это позволяет точно одна функция для доступа к закрытым членам класса. Так же, как c2
сделал. И точно так же, как c2
, единственная функция, которая имеет доступ, это не «какая-то случайная, неизвестная функция», а «функция, указанная в определении класса». Как и c2
, мы можем увидеть, просто взглянув на определения классов, полный список тех, кто имеет доступ.
Так как именно это менее инкапсулировано? Такое же количество кода имеет доступ к закрытым членам класса. И каждый , у кого есть доступ, указан в определении класса.
friend
не нарушает инкапсуляцию. Это заставляет некоторых программистов на Java чувствовать себя некомфортно, потому что когда они говорят «ООП», они на самом деле означают «Java». Когда они говорят «Инкапсуляция», они не означают «частные члены должны быть защищены от произвольного доступа», а «класс Java, где единственными функциями, которые могут получить доступ к закрытым членам, являются члены класса», хотя это полная чушь по нескольким причинам .
Во-первых, как уже показано, это слишком ограничивает. Нет причин, по которым методы друзей не должны делать то же самое.
Во-вторых, оно не является ограничительным достаточно . Рассмотрим четвертый класс:
class c4 {
public:
int getx();
void setx(int x);
private:
int x;
};
Это, согласно вышеупомянутому менталитету Java, идеально инкапсулировано.
И все же, он позволяет абсолютно любому читать и изменять x . Как это вообще имеет смысл? (подсказка: это не так)
Итог:
Инкапсуляция - это возможность контролировать, какие функции могут обращаться к частным членам. не о том, где именно находятся определения этих функций.