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 . Как это вообще имеет смысл? (подсказка: это не так)
Итог: инкапсуляция - это возможность контролировать, какие функции могут получить доступ к закрытым членам. Речь идет не о том, где именно находятся определения этих функций.