Почему я могу получить доступ к закрытым переменным в конструкторе копирования? - PullRequest
74 голосов
/ 07 ноября 2010

Я узнал, что никогда не смогу получить доступ к закрытой переменной, только с помощью функции get в классе. Но тогда почему я могу получить к нему доступ в конструкторе копирования?

Пример:

Field::Field(const Field& f)
{
  pFirst = new T[f.capacity()];

  pLast = pFirst + (f.pLast - f.pFirst);
  pEnd  = pFirst + (f.pEnd - f.pFirst);
  std::copy(f.pFirst, f.pLast, pFirst);
}

Моя декларация:

private:
  T *pFirst,*pLast,*pEnd;

Ответы [ 5 ]

103 голосов
/ 07 ноября 2010

Модификаторы доступа работают на уровне класса , а не на уровне объекта .

То есть два объекта одного класса могут получать доступ друг к другу к частным данным..

Почему:

Главным образом из-за эффективности.Было бы немалым накладным расходом времени выполнения проверять, если this == other каждый раз, когда вы обращаетесь к other.x, что вам нужно, если бы модификаторы доступа работали на уровне объекта.Думайте об этом с точки зрения области видимости: «Какую большую часть кода мне нужно иметь в виду при изменении частной переменной?»- Вы должны помнить код всего класса, и это ортогонально тому, какие объекты существуют во время выполнения.

И это невероятно удобно при написании конструкторов копирования и операторов присваивания.

33 голосов
/ 07 ноября 2010

Вы можете получить доступ к закрытым членам класса из класса, даже из другого экземпляра.

27 голосов
/ 18 июля 2013

ИМХО, существующие ответы плохо справляются с объяснением «почему» этого - слишком много внимания уделяется повторению того, какое поведение допустимо.«Модификаторы доступа работают на уровне класса, а не на уровне объекта».- да, но почему?

Общая концепция здесь заключается в том, что программист (ы) проектируют, пишут и поддерживают класс, который (как) должен понимать желаемую инкапсуляцию ОО и уполномочен координировать ее реализацию.Итак, если вы пишете class X, вы кодируете не только то, как отдельный объект X x может использоваться кодом с доступом к нему, но и то, как:

  • производные классывозможность взаимодействовать с ним (с помощью необязательно-чистых виртуальных функций и / или защищенного доступа) и
  • различных X объектов взаимодействующих для обеспечения намеченного поведения при соблюдении постусловий и инвариантовот вашего дизайна.

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

В частности, эти операции могут использовать привилегированный доступ для таких вещей, как:

  • (полицейскийy-конструкторы) используют закрытый член объекта "rhs" (правая сторона) в списке инициализатора, так что переменная-член сама создается копией вместо конструкции по умолчанию (если даже допустимой), а затем присваивается тоже (опять же, еслизаконный)
  • общий доступ к ресурсам - дескрипторы файлов, сегменты разделяемой памяти, shared_ptr s для ссылки на данные и т. д.
  • переходят во владение вещами, например auto_ptr<> "переносит" владение объектом вконструкция
  • копировать частные элементы «кэша», калибровки или состояния, необходимые для создания нового объекта в оптимально пригодном для использования состоянии без необходимости их регенерации с нуля.
  • копирование / доступ к диагностической информации / трассировке.в копируемом объекте, который иначе не доступен через общедоступные API, но может использоваться некоторым более поздним объектом исключения или журналированием (например, что-то о времени / обстоятельствах, когда был создан «оригинальный» не-созданный экземпляр)
  • выполнить более эффективное копирование некоторых данных: например, объекты могут иметь, например, unordered_map член, но публично предоставляет только итераторы begin() и end() - с прямым доступом к size() вы можете reserve емкость для более быстрого копирования;еще хуже, если они предоставляют только at() и insert(), а в противном случае throw ....
  • копируют ссылки обратно на родительские / координационные / управляющие объекты, которые могут быть неизвестны или доступны только для записи для клиентского кода
11 голосов
/ 23 мая 2012

Чтобы понять ответ, я хотел бы напомнить вам несколько понятий.

  1. Независимо от того, сколько объектов вы создаете, в памяти для этого класса есть только одна копия одной функции.Это означает, что функции создаются только один раз.Однако переменные являются отдельными для каждого экземпляра класса.
  2. this указатель передается каждой функции при вызове.

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

Надеюсь, это ответит на ваш вопрос.

6 голосов
/ 07 ноября 2010

Конструктор копирования является функцией-членом класса и, как таковой, имеет доступ к членам класса, даже если они объявлены как частные.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...