Почему объекты одного класса имеют доступ к личным данным друг друга?
class TrivialClass {
public:
TrivialClass(const std::string& data) :
mData(data) {};
const std::string& getData(const TrivialClass& rhs) const {
return rhs.mData;
};
private:
std::string mData;
};
int main() {
TrivialClass a("fish");
TrivialClass b("heads");
std::cout << "b via a = " << a.getData(b) << std::endl;
return 0;
}
Этот код работает. Для объекта a вполне возможно получить доступ к личным данным из объекта b и вернуть их. Почему это должно быть так? Я бы подумал, что личные данные являются личными. (Я начал с попытки понять конструкторы копирования в идиоме pimpl, но затем обнаружил, что даже не понимаю эту простую ситуацию.)
Ответы:
Потому что именно так это работает в C ++. В C ++ контроль доступа работает для каждого класса , а не для каждого объекта.
Контроль доступа в C ++ реализован как статическая функция времени компиляции. Я думаю, что довольно очевидно, что на самом деле невозможно реализовать какой-либо значимый контроль доступа для каждого объекта во время компиляции. Таким образом можно реализовать только управление для каждого класса.
Некоторые намеки на управление отдельными объектами присутствуют в спецификации защищенного доступа , поэтому в стандарте есть отдельная глава (11.5). Но все же любые описанные здесь индивидуальные особенности довольно элементарны. Опять же, контроль доступа в C ++ предназначен для работы на уровне каждого класса.
источник
void X::f(X&x)
языке компилятор легко распознаетthis->a
иx.a
. Компилятор не (всегда) может знать, что*this
иx
на самом деле являются одним и тем же объектом, еслиx.f(x)
он вызывается, но я мог очень хорошо видеть, что дизайнер языка нашел это нормально.this
и&x
являются ли они одинаковыми. Что еще хуже, это на самом деле становится проблемой дажеX::f(Y& y)
, потому что наш конкретный объект может иметь тип,Z
который наследуется от обоихX
иY
. Короче говоря, это настоящий беспорядок, неэффективный, сложно заставить работать с MI разумно.X::f(X& x)
, если есть доступx.a
, он не компилируется. Больше ничего не меняется, никаких проверок вставлять не нужно, поэтому на производительность еще действующих программ не влияет. И это предлагается не как критическое изменение существующего C ++, а как нечто, что дизайнеры могли бы сделать приprivate
первоначальном внедрении .«Частный» на самом деле не является механизмом контроля доступа в смысле «Я сделал свои фотографии на facebook частными, чтобы вы не могли их видеть».
В C ++ «частный» просто означает, что это части класса, которые вы (кодировщик класса) можете изменить в будущих версиях и т. Д., И вы не хотите, чтобы другие кодировщики, использующие ваш класс, полагались на их существование или функциональность. .
Если вам нужен настоящий контроль доступа, вам следует реализовать настоящие методы защиты данных.
источник
Это хороший вопрос, и я недавно столкнулся с ним. Я провел несколько дискуссий с моими коллегами, и вот краткое изложение нашего обсуждения: Это задумано. Это не означает, что этот дизайн полностью приемлем для всех случаев, но должны быть некоторые соображения, почему для каждого класса выбирается частный. Возможные причины, о которых мы могли бы подумать, включают:
Во-первых, стоимость управления доступом к экземпляру может быть очень высокой. Это обсуждалось другими в этой ветке. Теоретически это можно сделать с помощью этого проверки указателя. Однако это нельзя сделать во время компиляции, а можно сделать только во время выполнения. Таким образом, вы должны идентифицировать контроль доступа каждого члена во время выполнения, и когда он нарушается, возможно, будут возникать только исключения. Стоимость высока.
Во-вторых, управление доступом для каждого класса имеет собственный вариант использования, например конструктор копирования или оператор =. Их было бы сложно реализовать, если бы контроль доступа был индивидуальным.
Кроме того, контроль доступа осуществляется в основном с точки зрения программирования / языка, с точки зрения того, как модулировать / контролировать доступ к коду / члену, а не к данным.
источник
Это в некоторой степени произвольное дизайнерское решение языка. В Ruby , например, это
private
действительно означает частный, поскольку в «только экземпляр может получить доступ к своим собственным частным элементам данных». Однако это несколько ограничительно.Как указано в комментариях, конструкторы копирования и операторы присваивания - это обычные места, где вы напрямую получаете доступ к частным членам данных другого экземпляра. Есть менее очевидные причины.
Рассмотрим следующий случай. Вы реализуете объектно-ориентированный связанный список. Связанный список имеет вложенный класс узлов для управления указателями. Вы можете реализовать этот класс узла так, чтобы он сам управлял указателями (а не делал указатели общедоступными и управлялись списком). В таком случае у вас были бы объекты узлов, которые хотели бы изменить указатели других узловых объектов в других местах, где используется типичный конструктор копирования и оператор присваивания.
источник
Уловка заключается в том, чтобы помнить, что данные относятся
private
к классу , а не к экземпляру класса. Любой метод в вашем классе может получить доступ к закрытым данным любого экземпляра этого класса; не существует способа сохранить конфиденциальность данных внутри экземпляра, если только вы не запретите методы, которые явно обращаются к частным элементам данных других экземпляров.источник
В дополнение ко всем вышеперечисленным ответам рассмотрите настраиваемые конструкторы копирования, операторы присваивания и все другие функции, которые вы бы написали для класса, который работает с другими экземплярами . Для всех этих членов данных вам потребуются функции доступа.
источник
Личные данные остаются конфиденциальными до тех пор, пока кто-то, имеющий к ним доступ, не раскроет их другим.
Эта концепция применима и к другой ситуации, например:
Как можно было снять деньги? :)
источник