Programar em C++/Friend
Friend functions
O que é
Friend é um atributo especial de acesso a classes. Com ele declaramos que uma função fora de uma classe é amiga da mesma.
Declarando que uma função (externa á classe) "friend" dentro de uma classe, permite que a função (a amiga) possa ler e manipular membros (variáveis e funções membro) "private" - privados e "protected" - protegidos (e claro "public" - publicas, mas isso já era permitido antes de serem "friends").
Considerando que o acesso a membros pode ser restrito para determinadas partes do código, podemos adotar uma postura mais flexível para funções que conhecemos como confiáveis e evitar os inconvenientes da restrição a membros por códigos que não provoquem problemas maiores a nossa estrutura da aplicação.
Declarar funções "friend"
O processo para fazer com que funções fora do escopo da classe tenham acesso a membros sem nenhuma restrição é muito simples. Para isto apenas temos de colocar o protótipo da função externa dentro da classe precedido da palavra "friend". Desta forma o compilador passa a ignorar os atributos de restrição de acesso da classe quando a função acessa membros da mesma.
Vamos ao exemplo:
// friend functions
#include <iostream>
using namespace std;
class CRectangle
{
int width, height;
public:
void set_values (int, int);
int area () {return (width * height);}
friend CRectangle duplicate (CRectangle);
};
void CRectangle::set_values (int a, int b)
{
width = a;
height = b;
}
CRectangle duplicate (CRectangle rectparam)
{
CRectangle rectres;
rectres.width = rectparam.width*2;
rectres.height = rectparam.height*2;
return (rectres);
}
int main ()
{
CRectangle rect, rectb;
rect.set_values (2,3);
rectb = duplicate (rect);
cout << rectb.area();
system (“pause”);
return 0;
}
O uso de funções amigas deve ser evitado sempre que possível, pois diminui a identidade da orientação a objetos. Isto ocorre porque o uso desse mecanismo representa uma quebra no encapsulamento. Quando passamos a permitir que funções tenham acesso a membros restritos dos objetos fazemos com que agentes externos interfiram na autonomia dos mesmos. Isto pode dificultar a análise de programas muito extensos.
No caso da criação de procedimentos que tem a finalidade de modificar o conteúdo do objeto explicitamente, como nos casos de operadores e modificadores de comportamento, podemos usar as funções amigas "friends" para esta finalidade tomando os devidos cuidados para torná-las muito bem restritas as funções que devem executar. É muito importante observar se estas funções alteram dados dentro dos objetos que não podem ser modificados. Se as devidas precauções forem tomadas não haverá problemas no uso de funções "friend".
Friend classes
Da mesma forma que podemos declarar funções como amigas de uma determinada classe, podemos declarar outra classe como sua amiga. Este artifício faz com que os membros da classe onde foi feita a declaração sejam acessíveis à declarada. Assim, a segunda classe passa a ter possibilidade de manipulação livre dos membros da outra.
Apesar da funcionalidade ser um pouco semelhante à que temos no uso das funções, quando declaramos uma classe como "friend" dentro de outra, teremos todas as funções da primeira com poderes de acesso aos membros da segunda. Esta característica requer cuidado redobrado quando operações da classe "friend" interferem no conteúdo da outra.
// friend class
#include <iostream>
using namespace std;
class CSquare;
class CRectangle
{
int width, height;
public:
int area ()
{return (width * height);}
void convert (CSquare a); //consigo acessar porque é friend
};
class CSquare
{
private:
int side;
public:
void set_side (int a) {side=a;}
friend class CRectangle; //declaro friend class
};
void CRectangle::convert (CSquare a)
{
width = a.side;
height = a.side;
}
int main ()
{
CSquare sqr;
CRectangle rect;
sqr.set_side(4);
rect.convert(sqr);
cout << rect.area();
system (“pause”);
return 0;
}
Nota:
- Não há a propriedade de reciprocidade (ou reversão). O facto de uma função ou classe ser friend de uma classe não implica o contrário, ou seja, A ter B como friend não implica que B a tenha em mesma conta.
- Outra propriedade é que não há transitividade. Se numa class A for declarado que a class B é friend. E depois que na classe B estiver declarado que a classe C é friend de B,…Isto não implica que A seja friend de C.