IMHO, as respostas existentes explicam mal o "Porquê" disso - concentrando-se demais em reiterar qual comportamento é válido. "modificadores de acesso funcionam no nível da classe, e não no nível do objeto." - sim mas por quê?
O conceito abrangente aqui é que são os programadores que projetam, escrevem e mantêm uma classe de quem se espera que entendam o encapsulamento OO desejado e tenham o poder de coordenar sua implementação. Então, se você está escrevendo class X
, você está codificando não apenas como um X x
objeto individual pode ser usado pelo código com acesso a ele, mas também como:
- classes derivadas são capazes de interagir com ele (por meio de funções virtuais opcionalmente puras e / ou acesso protegido), e
X
objetos distintos cooperam para fornecer os comportamentos pretendidos, ao mesmo tempo que respeitam as pós-condições e invariantes de seu projeto.
Não é apenas o construtor de cópia - muitas operações podem envolver duas ou mais instâncias de sua classe: se você está comparando, adicionando / multiplicando / dividindo, construindo cópias, clonando, atribuindo etc., então é comum que você ou simplesmente deve ter acesso a dados privados e / ou protegidos no outro objeto, ou deseja permitir uma implementação de função mais simples, rápida ou geralmente melhor.
Especificamente, essas operações podem querer tirar proveito do acesso privilegiado para fazer coisas como:
- (construtores de cópia) usam um membro privado do objeto "rhs" (lado direito) em uma lista de inicializadores, de modo que uma variável de membro seja ela própria construída por cópia em vez de construída por padrão (se até mesmo válida) e então atribuída também (novamente, se legal)
- compartilhe recursos - identificadores de arquivo, segmentos de memória compartilhada,
shared_ptr
s para referenciar dados etc.
- apropriar-se das coisas, por exemplo,
auto_ptr<>
"move" a propriedade para o objeto em construção
- copie o "cache" privado, calibração ou membros do estado necessários para construir o novo objeto em um estado de uso ideal sem ter que regenerá-los do zero
- copiar / acessar informações de diagnóstico / rastreamento mantidas no objeto que está sendo copiado que não podem ser acessadas por meio de APIs públicas, mas podem ser usadas por algum objeto de exceção posterior ou registro (por exemplo, algo sobre o tempo / circunstâncias em que a instância "original" não construída por cópia foi construído)
- execute uma cópia mais eficiente de alguns dados: por exemplo, objetos podem ter, por exemplo, um
unordered_map
membro, mas publicamente apenas expor begin()
e end()
iteradores - com acesso direto a size()
você, pode ter reserve
capacidade para uma cópia mais rápida; pior ainda se eles apenas expõem at()
e insert()
e de outra forma throw
....
- copiar referências de volta para objetos pai / coordenação / gerenciamento que podem ser desconhecidos ou somente gravação para o código do cliente