Почему объекты одного класса имеют доступ к другим личным данным?

Почему объекты одного класса имеют доступ к другим личным данным?

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, но потом я обнаружил, что я даже не понял эту простую ситуацию.)

Ответ 1

Так как это работает на С++. В С++ управление доступом работает на основе каждого класса, а не на основе каждого объекта.

Контроль доступа в С++ реализован как статическая функция времени компиляции. Я думаю, что довольно очевидно, что на этапе компиляции реально невозможно реализовать какой-либо значимый контроль доступа к каждому объекту. Этот способ может быть реализован только для каждого класса.

Некоторые рекомендации по управлению объектами присутствуют в спецификации защищенного доступа, поэтому в стандарте (11.5) имеется даже отдельная глава. Но все же описанные там характеристики каждого объекта довольно рудиментарны. Опять же, управление доступом на С++ предназначено для работы на уровне каждого класса.

Ответ 2

"Private" на самом деле не является механизмом контроля доступа в смысле "Я сделал свои фотографии на facebook частным, чтобы вы их не видели".

В С++ "private" просто говорится, что это части класса, которые вы (кодер класса) можете изменить в будущих версиях и т.д., и вы не хотите, чтобы другие кодеры, использующие ваш класс, полагались на свои существования или функциональности.

Если вам нужен настоящий контроль доступа, вы должны внедрить подлинные методы защиты данных.

Ответ 3

Это хороший вопрос, и я недавно столкнулся с этим вопросом. У меня были некоторые дискуссии с моими коллегами, и вот резюме нашей дискуссии: Это по дизайну. Это не означает, что этот дизайн является полностью разумным для всех случаев, но должны быть некоторые соображения, почему выбрано для каждого класса. Возможные причины, о которых мы могли подумать, включают:

Прежде всего, стоимость контроля доступа к экземпляру может быть очень высокой. Об этом говорили другие в этой теме. Теоретически это можно сделать с помощью этой проверки указателя. Однако это невозможно сделать во время компиляции и может быть выполнено только во время выполнения. Таким образом, вы должны определить контроль доступа каждого участника во время выполнения, а когда он нарушит, возможно, будут только исключения. Стоимость высокая.

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

Кроме того, управление доступом в основном связано с перспективой программирования/языка, как модулировать/управлять доступом к коду/члену, а не данным.

Ответ 4

Это несколько произвольное решение для языкового дизайна. В Ruby, например, private действительно означает private, так как в "только экземпляр может обращаться к своим собственным частным данным". Однако это несколько ограничивает.

Как указано в комментариях, конструкторы копирования и операторы присваивания являются общими местами, где вы напрямую обращаетесь к другим частным частным данным экземпляра. Есть менее очевидные причины.

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

Ответ 5

Трюк заключается в том, чтобы помнить, что данные private относятся к классу, а не к экземпляру класса. Любой метод внутри вашего класса может получить доступ к личным данным любого экземпляра этого класса; там нет способа держать данные конфиденциальными внутри экземпляра, если вы не запрещаете методы, которые явно получают доступ к частным данным из других экземпляров.

Ответ 6

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

Ответ 7

Частные данные остаются закрытыми до тех пор, пока кто-то, у кого есть доступ к нему, не откроет его другим.

Эта концепция применима и к другой ситуации, например:

class cMyClass
{
public:
   // ...
   // omitted for clarity
   // ...

   void Withdraw(int iAmount)
   {
      iTheSecretVault -= iAmount;
   }

private:
   int iTheSecretVault;
};

Как кто-нибудь мог снять деньги?:)