Почему объекты одного класса имеют доступ к личным данным друг друга? - PullRequest
85 голосов
/ 03 августа 2011

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

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

Ответы [ 7 ]

73 голосов
/ 03 августа 2011

Потому что так работает в C ++.В C ++ управление доступом работает на основе для каждого класса , а не для каждого объекта.

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

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

28 голосов
/ 03 августа 2011

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

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

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

12 голосов
/ 27 октября 2015

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

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

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

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

11 голосов
/ 03 августа 2011

Это что-то вроде произвольного решения о дизайне языка.Например, в Ruby private действительно означает частный, поскольку в «только экземпляр может получить доступ к своим собственным частным элементам данных».Однако это несколько ограничивает.

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

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

4 голосов
/ 03 августа 2011

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

1 голос
/ 15 ноября 2017

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

0 голосов
/ 03 августа 2011

Личные данные остаются конфиденциальными, пока кто-то, имеющий к ним доступ, не откроет их другим.

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

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

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

private:
   int iTheSecretVault;
};

Как можно было снять деньги? :)

...