friend(C++)

경우에 따라 클래스가 클래스의 멤버가 아닌 함수 또는 별도의 클래스의 모든 멤버에 멤버 수준 액세스 권한을 부여하는 것이 유용합니다. 이러한 무료 함수 및 클래스를 친구라고 하며 키워드(keyword) 표시됩니다 friend . 클래스 구현자만 이 클래스의 friend를 선언할 수 있습니다. 함수 또는 클래스는 자신을 클래스의 친구로 선언할 수 없습니다. 클래스 정의에서 키워드(keyword) 및 비회원 함수 또는 기타 클래스의 이름을 사용하여 friend 클래스의 프라이빗 및 보호된 멤버에 대한 액세스 권한을 부여합니다. 템플릿 정의에서 형식 매개 변수를 .로 friend선언할 수 있습니다.

구문

friend-declaration:
friend function-declaration
friend function-definition
friendelaborated-type-specifier;;
friend simple-type-specifier ;
friend typename-specifier ;

friend 선언

이전에 선언되지 않은 함수를 friend 선언하면 해당 함수는 바깥쪽 비클래스 범위로 내보내집니다.

선언에 friend 선언된 함수는 키워드(keyword) 사용하여 extern 선언된 것처럼 처리됩니다. 자세한 내용은 extern를 참조하세요.

전역 범위를 가진 함수는 프로토타입 전에 함수로 friend 선언할 수 있지만 멤버 함수는 전체 클래스 선언이 표시되기 전에 함수로 friend 선언할 수 없습니다. 다음 코드는 이러한 선언이 실패하는 방법을 보여줍니다.

class ForwardDeclared;   // Class name is known.
class HasFriends
{
    friend int ForwardDeclared::IsAFriend();   // C2039 error expected
};

앞의 예제에서는 클래스 이름을 ForwardDeclared 범위에 입력하지만 전체 선언(특히 함수 IsAFriend를 선언하는 부분)은 알 수 없습니다. 클래스 HasFriendsfriend 선언은 오류를 생성합니다.

C++11에는 클래스에 대한 두 가지 형태의 friend 선언이 있습니다.

friend class F;
friend F;

첫 번째 양식은 가장 안쪽 네임스페이스에서 해당 이름의 기존 클래스를 찾을 수 없는 경우 새 클래스 F를 도입합니다. C++11: 두 번째 양식은 새 클래스를 도입하지 않습니다. 클래스가 이미 선언되었을 때 사용할 수 있으며 템플릿 형식 매개 변수 또는 typedeffriend로 선언할 때 사용해야 합니다.

참조된 형식이 아직 선언되지 않은 경우 사용합니다 friend class F .

namespace NS
{
    class M
    {
        friend class F;  // Introduces F but doesn't define it
    };
}

선언되지 않은 클래스 형식과 함께 사용하는 friend 경우 오류가 발생합니다.

namespace NS
{
    class M
    {
        friend F; // error C2433: 'NS::F': 'friend' not permitted on data declarations
    };
}

다음 예제 friend F 에서는 NS 범위 외부에서 선언된 클래스를 참조 F 합니다.

class F {};
namespace NS
{
    class M
    {
        friend F;  // OK
    };
}

템플릿 매개 변수를 friend로 선언하는 데 사용합니다 friend F .

template <typename T>
class my_class
{
    friend T;
    //...
};

typedef를 friend로 선언하는 데 사용합니다 friend F .

class Foo {};
typedef Foo F;

class G
{
    friend F; // OK
    friend class F // Error C2371 -- redefinition
};

서로 friend인 두 클래스를 선언하려면 두 번째 클래스 전체가 첫 번째 클래스의 friend로 지정되어야 합니다. 이러한 제한은 컴파일러가 두 번째 클래스가 선언된 지점에서만 개별 friend 함수를 선언하는 데 충분한 정보를 갖기 때문에 발생합니다.

참고 항목

두 번째 클래스 전체가 첫 번째 클래스의 friend여야 하지만, 두 번째 클래스의 friend가 될 첫 번째 클래스의 함수를 선택할 수 있습니다.

friend 함수

friend 함수는 클래스의 멤버가 아니지만 클래스의 프라이빗 및 보호된 멤버에 액세스할 수 있는 함수입니다. Friend 함수는 클래스 멤버로 간주되지 않습니다. 특수한 액세스 권한이 부여되는 일반적인 외부 함수입니다. 친구는 클래스의 범위에 있지 않으며 다른 클래스의 멤버가 아니면 멤버 선택 연산자( ->)를 사용하여 호출되지 않습니다. friend 함수는 액세스 권한을 부여하는 클래스에 의해 선언됩니다. 선언은 friend 클래스 선언의 아무 곳에나 배치할 수 있습니다. 액세스 제어 키워드(keyword) 영향을 받지 않습니다.

다음 예제에서는 Point 클래스와 ChangePrivate라는 friend 함수를 보여 줍니다. 함수는 friend 매개 변수로 수신하는 개체의 Point 프라이빗 데이터 멤버에 액세스할 수 있습니다.

// 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
}

Friend 클래스 멤버

클래스 멤버 함수는 다른 클래스에서 friend로 선언될 수 있습니다. 다음 예제를 참조하세요.

// 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

앞의 예제에서는 함수 A::Func1( B& ) 에만 클래스B에 대한 액세스 권한이 부여됩니다friend. 따라서 프라이빗 멤버 _b 에 대한 액세스는 클래스 A 에서 Func1 올바르지만 Func2.

friend 클래스는 멤버 함수 friend 가 클래스의 함수인 모든 클래스, 즉 멤버 함수가 다른 클래스의 프라이빗 및 보호된 멤버에 액세스할 수 있는 클래스입니다. friend 클래스의 B 선언이 다음과 같다고 가정합니다.

friend class A;

이 경우 클래스의 모든 멤버 함수에 클래스 AB에 대한 액세스 권한이 부여됩니다friend. 다음 코드는 클래스의 예입니다.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();
}

우정은 명시적으로 지정되지 않는 한 상호가 아닙니다. 위의 예제에서 멤버 함수는 .의 YourClass 프라이빗 멤버 YourOtherClass에 액세스할 수 없습니다.

관리되는 형식(C++/CLI)에는 함수, friend 클래스 또는 friend 인터페이스가 있을 friend 수 없습니다.

우정은 상속되지 않습니다. 즉, 파생된 YourOtherClass 클래스는 '개인 멤버'에 액세스할 YourClass수 없습니다. 우정은 전이적이지 않으므로 친구의 수업 YourOtherClass 은 '개인 회원'에 액세스 YourClass할 수 없습니다.

다음 그림에서는 Base, Derived, aFriendanotherFriend라는 네 가지 클래스 선언을 보여 줍니다. aFriend 클래스만 Base 전용 멤버(및 Base에서 상속했을 수 있는 모든 멤버)에 직접 액세스할 수 있습니다.

A diagram that shows the derivation implications of a friend relationship.

다이어그램은 다른Friend 클래스가 friend가 aFriend 클래스인 클래스 베이스와 친구 관계가 없는 것을 보여줍니다. 클래스 aFriend는 클래스 Base에서 친구이지만 파생 클래스가 Base에서 상속되더라도 클래스 Derived와 friend 관계가 없습니다. 이는 상속이 파생 클래스에 기본 클래스와 동일한 친구가 있음을 의미하지는 않음을 보여 줍니다.

인라인 friend 정의

Friend 함수는 클래스 선언 내에서 정의(함수 본문 제공)할 수 있습니다. 이러한 함수는 인라인 함수입니다. 멤버 인라인 함수와 마찬가지로 모든 클래스 멤버가 표시된 직후에 정의된 것처럼 동작하지만 클래스 범위를 닫기 전에(클래스 선언의 끝에) 동작합니다. 클래스 선언 내에 정의된 Friend 함수는 바깥쪽 클래스의 범위에 있습니다.

참고 항목

키워드