2011-10-16 2 views
39

같은 코드가있다 :액세스 친구 기능은 클래스에 정의

#include <iostream> 

class A{ 

public: 
    friend void fun(A a){std::cout << "Im here" << std::endl;} 
    friend void fun2(){ std::cout << "Im here2" << std::endl; } 
    friend void fun3(); 
}; 

void fun3(){ 
    std::cout << "Im here3" << std::endl; 
} 

int main() 
{ 
    fun(A()); // works ok 
    //fun2(); error: 'fun2' was not declared in this scope 
    //A::fun2(); error: 'fun2' is not a member of 'A' 
    fun3(); // works ok 
} 

어떻게 액세스 할 수있는 기능 Fun2에가()?

+6

+1 : 잘 공식화 된 질문입니다. –

+0

우리는 부스트의 스마트 포인터 인 intrusive_ptr에서 이런 종류의 코드를 보았습니다. 나에게 그것은 그것을 정의하는 것이 의미가 없다. 오히려 범위 내의 어딘가에서 친구를 정의하고 클래스 범위 선언에서 프로토 타입을 친구로 표시한다. 이것은 더 읽기 쉽다. – Gabriel

답변

34
class A{ 

public: 
    friend void fun(A a){std::cout << "Im here" << std::endl;} 
    friend void fun2(){ std::cout << "Im here2" << std::endl; } 
    friend void fun3(); 
}; 

, 당신은 여전히 ​​동일한 기능의 선언을 누락 글로벌 범위 자체에서.

즉, 해당 범위의 코드에는 fun2이라는 아이디어가 없습니다.

A 형식의 인수가 있기 때문에 인수 종속적 조회가 인계 받아 함수를 찾을 수 있다는 점을 제외하면에 대해서도 동일한 문제가 발생합니다.

내가 대신 일반적인 방식으로 함수를 정의하는 것이 좋습니다 :

class A { 
    friend void fun(A a); 
    friend void fun2(); 
    friend void fun3(); 
}; 

void fun(A a) { std::cout << "I'm here" << std::endl; } 
void fun2() { std::cout << "I'm here2" << std::endl; } 
void fun3(); 

공지 사항을 지금 everything works (내가 그것을 정의되지 않기 때문에 fun3 제외).

21

fun을 호출 할 수있는 이유는 클래스 A의 친구 선언이 인수 종속 검색을 통해서만 표시된다는 것입니다. 그렇지 않으면 친구 선언은 나타나는 클래스 범위 외부에서 자동으로 표시되는 기능을 만들지 않습니다.

mainfun2을 표시하려면 namespace 범위 또는 main에 선언을 추가해야합니다.

예. (클래스의 외부)의 정의로부터 main가 표시하게 선언이기도하므로

void fun2(); 

fun3main이 안에 표시된다.

ISO/IEC 14882 : 2011 7.3.1.2 :

친구의 이름은 규정되지 않은 조회 (3.4.1) 또는 일치하는 선언이 될 때까지 자격 조회 (3.4.3)에 의해 발견되지

(클래스 정의가 우정을 부여하기 전이나 후에) 네임 스페이스 범위에서 제공된다.

3.4.2 (인수 종속 이름 조회)/4

상관 친구 기능 또는 관련 클래스에 선언 친구 기능 템플릿들이없는 경우에도 각 네임 스페이스 내에서 볼 수 스페이스 스코프 일반적인 조회 (11.3) 중에 표시됩니다. fun2의 당신의 정의는 동시에 Afriend을 오히려 구성원보다 "글로벌"기능을 정의하고, 그것을 만드는 않지만

+0

전역 네임 스페이스에 선언을 배치하면 문제가 해결되지만 주 기능에 배치하면 링커 오류가 발생합니다. 감사. – scdmb

+0

@scdmb : 링커 오류에 놀랍습니다. 유효해야합니다. –

+0

아니요, _definition-declaration_를'main'에두면 [_compiler_ 오류가 발생합니다] (http://codepad.org/KrhX3kHL). [찰스가 제안한 것은 정확하다] (http://codepad.org/ERZrmowu). 그리고 다음 번에는 그와 같은 오류 보고서를 다시 볼 때마다 테스트 케이스를 제공하십시오. 선언과 정의의 차이점에 대해서는 C++ 책을 참조하십시오. –

관련 문제