Por que a amizade não é pelo menos opcionalmente herdada em C ++? Eu entendo que a transitividade e a reflexividade são proibidas por razões óbvias (digo isso apenas para evitar respostas simples de citação do FAQ), mas a falta de algo parecido com o que virtual friend class Foo;
me intriga. Alguém conhece os antecedentes históricos por trás dessa decisão? A amizade era realmente apenas um hack limitado que desde então encontrou seu caminho para alguns usos obscuros e respeitáveis?
Edite para esclarecimento: estou falando sobre o seguinte cenário, não onde os filhos de A são expostos a B ou a B e seus filhos. Também posso imaginar a concessão de acesso opcional para substituições de funções de amigo, etc.
class A {
int x;
friend class B;
};
class B {
// OK as per friend declaration above.
void foo(A& a, int n) { a.x = n; }
};
class D : public B { /* can't get in A w/o 'friend class D' declaration. */ };
Resposta aceita: como afirma Loki , o efeito pode ser simulado mais ou menos criando funções de proxy protegidas em classes base amigas, portanto, não há necessidade estrita de conceder amizade a uma classe ou hierarquia de método virtual. Não gosto da necessidade de proxies clichê (que a base de amigos efetivamente se torna), mas suponho que isso foi considerado preferível a um mecanismo de linguagem que provavelmente seria mal utilizado na maioria das vezes. Acho que provavelmente é hora de comprar e ler The Design and Evolution of C ++ , de Stroupstrup , que já vi muitas pessoas recomendarem, para ter uma visão melhor sobre esses tipos de perguntas ...
Acho que a resposta à sua primeira pergunta está nesta pergunta: "Os amigos de seu pai têm acesso às suas partes íntimas?"
fonte
Uma classe com amizade pode expor seu amigo por meio de funções de acesso e, em seguida, conceder acesso por meio delas.
Isso permite um controle mais preciso do que a transitividade opcional. Por exemplo,
get_cash
pode serprotected
ou pode impor um protocolo de acesso limitado em tempo de execução.fonte
;)
Padrão C ++, seção 11.4 / 8
Se a amizade fosse herdada, então uma classe que não era para ser um amigo de repente teria acesso aos internos da classe e isso viola o encapsulamento.
fonte
Porque é simplesmente desnecessário.
O uso da
friend
palavra-chave é em si suspeito. Em termos de acoplamento, é o pior relacionamento (muito à frente da herança e da composição).Qualquer mudança no interior de uma classe corre o risco de impactar os amigos dessa classe ... você realmente quer um número desconhecido de amigos? Você nem mesmo seria capaz de listá-los se aqueles que herdam deles também pudessem ser amigos, e você correria o risco de quebrar o código de seus clientes todas as vezes, certamente isso não é desejável.
Admito francamente que, para tarefas de casa / projetos de estimação, a dependência costuma ser uma consideração distante. Em projetos de pequeno porte, isso não importa. Mas assim que várias pessoas trabalharem no mesmo projeto e isso crescer para as dezenas de milhares de linhas, você precisará limitar o impacto das mudanças.
Isso traz uma regra muito simples:
Mudar o interior de uma classe só deve afetar a própria classe
Claro, você provavelmente afetará seus amigos, mas há dois casos aqui:
std::ostream& operator<<(...)
aqui, que não é um membro puramente por acidente das regras de idiomaEu recomendaria o uso do método simples:
Este
Key
padrão simples permite que você declare um amigo (de certa forma) sem realmente dar a ele acesso aos seus internos, isolando-o, assim, de alterações. Além disso, permite que este amigo empreste sua chave para administradores (como crianças), se necessário.fonte
Uma suposição: se uma classe declara alguma outra classe / função como amiga, é porque essa segunda entidade precisa de acesso privilegiado à primeira. Qual a utilidade de conceder à segunda entidade acesso privilegiado a um número arbitrário de classes derivadas da primeira?
fonte
B
teria acesso a todas as classes herdadas deA
...Uma classe derivada pode herdar apenas algo, que é 'membro' da base. Uma declaração de amigo não é membro da classe de amizade.
e mais
Visto que o 'amigo' não é membro da classe base em primeiro lugar, como pode ser herdado pela classe derivada?
fonte
A função de amigo em uma classe atribui a propriedade extern à função. ou seja, extern significa que a função foi declarada e definida em algum lugar fora da classe.
Portanto, significa que a função de amigo não é membro de uma classe. Portanto, a herança só permite que você herde as propriedades de uma classe, não coisas externas. E também se a herança for permitida para funções de amigo, então uma herança de classe de terceiros.
fonte
Friend é bom em herança como interface de estilo para contêiner Mas para mim, como digo primeiro, C ++ não possui a herança propagável
Para mim, o problema do C ++ é a falta de granularidade muito boa para controlar todo o acesso de qualquer lugar para qualquer coisa:
amigo Thing pode se tornar amigo Thing. * para conceder acesso a todos os filhos de Thing
E mais, amigo [área nomeada] Thing. * Para conceder acesso para uma área precisa na classe Container via área com nome especial para o amigo.
Ok, pare o sonho. Mas agora, você conhece um uso interessante de amigo.
Em outra ordem, você também pode achar interessante saber que todas as classes são amigáveis consigo mesmas. Em outras palavras, uma instância de classe pode chamar todos os
membros de outra instância de mesmo nome sem restrição:
fonte
Lógica simples: 'Eu tenho uma amiga Jane. Só porque nos tornamos amigos ontem, não faz com que todos os amigos dela sejam meus.
Ainda preciso aprovar essas amizades individuais, e o nível de confiança seria adequado.
fonte