Compartilhar via


friend (C++)

Em algumas circunstâncias, é útil para uma classe conceder acesso no nível do 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 amigos, marcadas pela friend palavra-chave. Somente o implementador de classe pode declarar quem são seus amigos. Uma função ou classe não pode se declarar como um amigo de qualquer classe. Em uma definição de classe, use a friend palavra-chave e o nome de uma função não membro ou outra classe para conceder-lhe 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 ;

friend Declarações

Se você declarar uma friend função que não foi declarada anteriormente, essa função será exportada para o escopo de não classe delimitador.

As funções declaradas em uma friend declaração são tratadas como se tivessem sido declaradas usando a extern palavra-chave. Para obter mais informações, consulte extern.

Embora as funções com escopo global possam ser declaradas como friend funções antes de seus protótipos, as funções membro não podem ser declaradas como friend funções antes da aparência de sua declaração de classe completa. 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 ForwardDeclared da classe no escopo, mas a declaração completa (especificamente, a parte que declara a função IsAFriend) não é conhecida. a friend declaração na classe HasFriends gera um erro.

No C++11, há duas formas de declarações de amigos para uma classe:

friend class F;
friend F;

O primeiro formulário introduz uma nova classe F se nenhuma classe existente por esse nome foi encontrada no namespace mais interno. C++11: o segundo formulário não apresenta 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 como typedef 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 que é 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 umas das outras, toda a segunda classe deve ser especificada como amiga da primeira classe. O motivo dessa restrição é que o compilador tem informações suficientes para declarar funções amigas individuais apenas no ponto em que a segunda classe é declarada.

Observação

Embora toda a segunda classe precise ser amiga da primeira classe, você pode selecionar quais funções na primeira classe serão amigas da segunda classe.

funções amigas

Uma friend função é uma função que não é membro de uma classe, mas tem acesso aos membros privados e protegidos da classe. As funções friend não são consideradas membros da classe; são funções externas normais que recebem privilégios especiais de acesso. Os amigos não estão no escopo da classe e não são chamados usando os operadores de seleção de membro (e ->) a menos que sejam membros de outra classe. Uma friend função é declarada pela classe que está concedendo acesso. A friend declaração pode ser colocada em qualquer lugar na declaração de classe. Ela não é afetada pelas palavras-chave de controle de acesso.

O exemplo a seguir mostra uma Point classe e uma função de amigo. ChangePrivate A friend função tem acesso ao membro de dados privados do Point objeto que recebe como 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 de 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& ) recebe friend acesso à classe B. Portanto, o acesso ao membro _b privado está correto na Func1 classe A , mas não em Func2.

Uma friend classe é uma classe cujas funções de membro são friend funções de uma classe, ou seja, cujas funções de membro têm acesso aos membros privados e protegidos da outra classe. Suponha que a friend declaração na classe B tenha sido:

friend class A;

Nesse caso, todas as funções de membro na classe A teriam recebido friend acesso à classe B. O código seguinte é um exemplo de uma friend classe:

// 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();
}

Amizade não é mútua a menos que explicitamente especificada como tal. No exemplo acima, as funções de YourClass membro não podem acessar os membros privados de YourOtherClass.

Um tipo gerenciado (em C++/CLI) não pode ter friend funções, friend classes ou friend interfaces.

A amizade não é herdada, o que significa que classes derivadas YourOtherClass de não podem acessar YourClassmembros privados. A amizade não é transitiva, então classes que são amigas YourOtherClass não podem acessar YourClassmembros privados.

A figura a seguir mostra quatro declarações de classe: Base, , Derivede aFriendanotherFriend. Somente a classe aFriend tem acesso direto aos membros privados ( Base e a qualquer membro Base pode ter herdado).

Um diagrama que mostra as implicações de derivação de uma relação de amigo.

O diagrama mostra que a classe anotherFriend não tem uma relação de amigo com a base de classe que os amigos classe aFriend. Classe aFriend é amiga da classe Base, mas não tem uma relação amigável com a classe Derivada, embora a classe Derivada herda 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 embutidas friend

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. Assim como as funções embutidas do membro, elas se comportam como se fossem definidas imediatamente após todos os membros da classe terem sido vistos, mas antes que o escopo da 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 delimitador.

Consulte também

Palavras-chave