ІМХО, існуючі відповіді погано спрацьовують питання "чому" цього - занадто багато зосереджуючись на повторенні того, яка поведінка є дійсною. "модифікатори доступу працюють на рівні класу, а не на рівні об'єкта." - так, але чому?
Основною концепцією тут є те, що саме програміст (и) розробляє, пише та підтримує клас, який (як очікується) зрозуміє бажану інкапсуляцію ОО та наділений повноваженнями координувати її реалізацію. Отже, якщо ви пишете class X
, ви кодуєте не просто те, як окремий X x
об’єкт може використовуватися кодом з доступом до нього, а й те, як:
- похідні класи можуть взаємодіяти з ним (за вибором - чисто віртуальні функції та / або захищений доступ), і
- окремі
X
об'єкти співпрацюють, щоб забезпечити передбачувану поведінку, одночасно дотримуючись пост-умов та інваріантів вашого дизайну.
Це не тільки конструктор копіювання - дуже багато операцій можуть включати два або більше екземплярів вашого класу: якщо ви порівнюєте, додаєте / множите / ділите, копіюєте, конструюєте, клонуєте, присвоюєте тощо, то часто трапляється так, що ви або просто повинен мати доступ до приватних та / або захищених даних в іншому об'єкті, або хотіти, щоб він дозволяв простішу, швидшу або, як правило, кращу реалізацію функції.
Зокрема, ці операції можуть захотіти скористатися привілейованим доступом, щоб робити такі речі:
- (конструктори копіювання) використовують приватний член об'єкта "rhs" (праворуч) у списку ініціалізатора, так що змінна члена сама створюється за копією замість побудованої за замовчуванням (якщо навіть легальна), а потім теж призначається (знову ж якщо законно)
- спільний доступ до ресурсів - дескриптори файлів, сегменти спільної пам'яті,
shared_ptr
s для посилань на дані тощо.
- взяти у власність речі, наприклад,
auto_ptr<>
" перенести " право власності на об'єкт, що будується
- копіювати приватний "кеш", калібрування або члени стану, необхідні для побудови нового об'єкта в оптимально зручному стані без необхідності їх регенерації з нуля
- копіювати / отримувати інформацію про діагностику / трасування, що зберігається в об'єкті, який копіюється, інакше не доступний через загальнодоступні API, але може бути використаний якимсь пізнішим об'єктом виключення або реєстрацією (наприклад, щось про час / обставини, коли "оригінальний" екземпляр, створений без копіювання був побудований)
- виконувати більш ефективну копію деяких даних: наприклад, об’єкти можуть мати, наприклад,
unordered_map
члена, але загальнодоступні лише викриття begin()
та end()
ітератори - з прямим доступом до size()
вас може reserve
бути швидшим копіюванням; ще гірше , якщо вони тільки викрити at()
і insert()
в іншому випадку throw
....
- копіювати посилання назад до батьківських / координаційних / керуючих об’єктів, які можуть бути невідомими або лише для запису для клієнтського коду