friend
(C++)
Em algumas circunstâncias, é útil que uma classe conceda acesso ao nível de membro a funções que não são membros da classe ou a todos os membros em uma classe separada. Essas funções e classes gratuitas são conhecidas como amigas, marcadas pela palavra-chave friend
. Somente o implementador de classe pode declarar quem são seus amigos. Uma função ou classe não pode se declarar como amiga de nenhuma classe. Em uma definição de classe, use a palavra-chave e o nome de uma função não membro ou outra classe para conceder a friend
ela acesso aos membros privados e protegidos de sua classe. Em uma definição de modelo, um parâmetro de tipo pode ser declarado como um friend
.
Sintaxe
friend-declaration
:
friend
function-declaration
friend
function-definition
friend
elaborated-type-specifier
;
;
friend
simple-type-specifier
;
friend
typename-specifier
;
Declarações friend
Se você declarar uma função friend
que não tenha sido declarada anteriormente, essa função será exportada para o escopo de envolvimento sem classe.
As funções declaradas em uma declaração friend
são tratadas como se tivessem sido declaradas usando a palavra-chave extern
. Para obter mais informações, consulte extern
.
Ainda que as funções com escopo global possam ser declaradas como friend
antes dos protótipos, as funções de membro não podem ser declaradas como friend
antes de aparecer a declaração completa de sua classe. O código a seguir mostra como essa declaração falha:
class ForwardDeclared; // Class name is known.
class HasFriends
{
friend int ForwardDeclared::IsAFriend(); // C2039 error expected
};
O exemplo anterior insere o nome da classe ForwardDeclared
no escopo, mas a declaração completa (especificamente, a parte que declara a função IsAFriend
) não é conhecida. a declaração friend
na classe HasFriends
gera um erro.
No C++11, há dois formulários de declarações de amigos para uma classe:
friend class F;
friend F;
O primeiro formulário introduz uma nova classe F, caso nenhuma classe existente por esse nome seja encontrada no namespace mais interno. C++11: o segundo formulário não introduz uma nova classe; ele pode ser usado quando a classe já foi declarada e deve ser usada ao declarar um parâmetro de tipo de modelo ou um typedef
como um friend
.
Use friend class F
quando o tipo referenciado ainda não tiver sido declarado:
namespace NS
{
class M
{
friend class F; // Introduces F but doesn't define it
};
}
Ocorrerá um erro se você usar friend
com um tipo de classe que não foi declarado:
namespace NS
{
class M
{
friend F; // error C2433: 'NS::F': 'friend' not permitted on data declarations
};
}
No exemplo a seguir, friend F
refere-se à F
classe declarada fora do escopo do NS.
class F {};
namespace NS
{
class M
{
friend F; // OK
};
}
Use friend F
para declarar um parâmetro de modelo como um amigo:
template <typename T>
class my_class
{
friend T;
//...
};
Use friend F
para declarar um typedef como amigo:
class Foo {};
typedef Foo F;
class G
{
friend F; // OK
friend class F // Error C2371 -- redefinition
};
Para declarar duas classes que são amigas da outro, a segunda classe inteira deve ser especificada como amiga de primeira classe. A razão para essa restrição é que o compilador tem informações suficientes para declarar funções individuais de amigo somente no ponto onde a segunda classe é declarada.
Observação
Embora a segunda classe inteira deve ser amiga da primeira classe, você pode selecionar quais funções na primeira classe serão amigas da segunda classe.
funções friend
Uma função friend
é uma função que não é membro de uma classe, mas que tem acesso a membros particulares e protegidos da classe. As funções friend não são consideradas membros de classe; elas são funções externas normais que recebem privilégios de acesso especiais. As funções amigo não estão no escopo da classe e não são chamadas usando os operadores da seleção de membro (. e –>) a menos que sejam membros de outra classe. Uma função friend
é declarada pela classe que está concedendo acesso. A declaração friend
pode ser colocada em qualquer lugar da declaração da classe. Ela não é afetada pelas palavras-chave de controle de acesso.
O exemplo a seguir mostra uma classe Point
e uma função friend, ChangePrivate
. A função friend
tem acesso ao membro de dados particular do objeto Point
que ela recebe como um parâmetro.
// friend_functions.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;
class Point
{
friend void ChangePrivate( Point & );
public:
Point( void ) : m_i(0) {}
void PrintPrivate( void ){cout << m_i << endl; }
private:
int m_i;
};
void ChangePrivate ( Point &i ) { i.m_i++; }
int main()
{
Point sPoint;
sPoint.PrintPrivate();
ChangePrivate(sPoint);
sPoint.PrintPrivate();
// Output: 0
1
}
Membros da classe como amigos
As funções de membro da classe podem ser declaradas como amigos em outras classes. Considere o seguinte exemplo:
// classes_as_friends1.cpp
// compile with: /c
class B;
class A {
public:
int Func1( B& b );
private:
int Func2( B& b );
};
class B {
private:
int _b;
// A::Func1 is a friend function to class B
// so A::Func1 has access to all members of B
friend int A::Func1( B& );
};
int A::Func1( B& b ) { return b._b; } // OK
int A::Func2( B& b ) { return b._b; } // C2248
No exemplo anterior, somente a função A::Func1( B& )
tem acesso de friend
para a classe B
. Em virtude disso, o acesso ao membro particular _b
está correto em Func1
da classe A
, mas não em Func2
.
Uma classe friend
é uma classe cujas funções membro são as funções friend
de uma classe, ou seja, cujas funções membro tenham acesso aos outros membros particulares e protegidos da classe. Suponha que a declaração friend
na classe B
fosse:
friend class A;
Nesse caso, todas as funções membro na classe A
receberão acesso de friend
para a classe B
. O código a seguir é um exemplo de uma classe friend
:
// classes_as_friends2.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;
class YourClass {
friend class YourOtherClass; // Declare a friend class
public:
YourClass() : topSecret(0){}
void printMember() { cout << topSecret << endl; }
private:
int topSecret;
};
class YourOtherClass {
public:
void change( YourClass& yc, int x ){yc.topSecret = x;}
};
int main() {
YourClass yc1;
YourOtherClass yoc1;
yc1.printMember();
yoc1.change( yc1, 5 );
yc1.printMember();
}
A amizade não é mútua a menos que explicitamente especificada como tal. No exemplo anterior, as funções membro de YourClass
não podem acessar os membros privados de YourOtherClass
.
Um tipo gerenciado (em C++/CLI) não pode ter nenhuma função friend
, classes friend
ou interfaces friend
.
A amizade não é herdada, o que significa que as classes derivadas de YourOtherClass
não podem acessar os membros particulares de YourClass
. A amizade não é transitiva, assim as classes que são amigos de YourOtherClass
não podem acessar membros particulares de YourClass
.
A figura a seguir mostra quatro declarações de classe: Base
, Derived
, aFriend
e anotherFriend
. Somente a classe aFriend
tem acesso direto aos membros privados de Base
(e a todos os membros que Base
pode ter herdado).
O diagrama mostra que a classe anotherFriend não tem uma relação de amizade com a base da classe que os amigos classe aFriend. A classe aFriend é amiga da classe Base, mas não tem uma relação de amizade com a classe Derivada, mesmo que a classe Derived herde da Base. Isso demonstra que a herança não implica que a classe derivada tenha os mesmos amigos que a classe base.
Definições friend
embutidas
As funções friend podem ser definidas (dado um corpo de função) dentro de declarações de classe. Essas funções são funções embutidas. Como funções membro embutidas, elas se comportam como se fossem definidas imediatamente após todos os membros de classe terem sido vistos, mas antes que o escopo de classe seja fechado (no final da declaração de classe). As funções friend que são definidas dentro de declarações de classe estão no escopo da classe delimitadora.
Confira também
Comentários
https://aka.ms/ContentUserFeedback.
Em breve: Ao longo de 2024, eliminaremos os problemas do GitHub como o mecanismo de comentários para conteúdo e o substituiremos por um novo sistema de comentários. Para obter mais informações, consulteEnviar e exibir comentários de