인프런 커뮤니티 질문&답변
내부클레스의 friend선언 중 errorC2511
작성
·
320
1
안녕하세요, C++을 수강하는 타전공 학생입니다. 항상 양질의 강의와 수준높은 커뮤니티 질답에 감탄하며 감사히 수강하고 있습니다.
8.12 친구 함수와 클래스 friend강의의 마지막 부분에서 문득 한 클래스에만 friend 키워드를 쓰면 그 클래스의 내부 클래스에 저장된 private 멤버도 접근 가능하게 되는지 궁금해져서 다음과 같이 실험해보았습니다.
#include <iostream>
using namespace std;
class A; // forward declaration
class B
{
private:
int m_value = 2;
public:
void doSomething(A& a, A::C& c);
};
class A
{
private:
int m_value = 1;
public:
// ---내부 클래스 C 추가----
class C
{
private:
int m_value = 3;
friend void B::doSomething(A& a, A::C& c); // 오류 발생!
};
//--------------------------
friend void B::doSomething(A& a, A::C& c); // 오류 발생!
};
void B::doSomething(A& a, A::C& c)
{
cout << a.m_value + c.m_value << endl;
}
int main()
{
A a;
B b;
A::C c;
b.doSomething(a, c);
return 0;
}
클래스 A에 private멤버를 가진 내부 클래스 C를 추가하고 doSomething함수를 A와 C의 private멤버 둘다 사용하도록 조금 바꿨습니다.
주석 표시한 곳에 클래스 B내 doSomething멤버함수에 대한 선언이 incompatible하다는 오류가 발생합니다.
그리고 컴파일 해보니 어마어마한 컴파일에러가 나오는데, 근본적인 에러는 아래인거 같습니다.
error C2511: 'void B::doSomething(A &,A::C &)': overloaded member function not found in 'B'
오버로드될 여지가 없어보이고, 함수이름, 파라미터를 토씨하나 안틀리고 복붙했는데..
왜 이런 오류가 나는 걸까요?
위 오류가 난 두 줄을 friend class B;로 바꾸면 IDE상에선 오류가 없지만 여전히 위 컴파일에러가 뜨네요.
한편 궁금증으로 돌아가서, 첫 번째 오류 줄인 friend void B::doSomething(A& a, A::C& c);을 지워봤습니다.
doSomething함수 내에서 A::C의 private멤버를 접근할 수 없다고 하는 것을 보니 내부 클래스 역시 따로 friend선언을 해주어야 하는거 같은데.. 오류가 떠서 확인할 수는 없었습니다.
답변 1
2
class A; 하고 전방 선언 해주었던 이유는 class B 가 dosomething 멤버 함수를 정의하는데에 있어 "A 라고 하는 클래스라는게 존재한다."라는 것을 미리 알려주기 위함이였죠.
이 말은 즉슨 A 의 중첩 클래스인 C 클래스의 존재에 대해서도 B 에게 알려주어야 한다는 뜻이기도 합니다. class A; 는 A 라는 클래스가 존재한다는 것만 알려주는거지 A 클래스 안에 C 클래스도 있어 라는 정보까지는 포함하지 못하니까요. 중첩클래스인 C 도 B 에게 존재를 알리기 위해 전방선언이 불가피합니다. 즉 class A::C; 전방 선언도 해주어야 한다는 의미입니다.
그러나 중첩 클래스는 컨테이너 바깥에선 전방선언이 불가능합니다.(링크 참고) 즉, B 에게 A::C 를 알려줄 수 없다는 것입니다. class A::C; 가 가능하지 않습니다.
https://stackoverflow.com/questions/1021793/how-do-i-forward-declare-an-inner-class
이를 우회할 다른 방법이 있는지에 대해선.. 저도 거기까진 잘 모르겠지만 이런 경우엔 굳이 중첩 클래스를 쓰지 않고 C 클래스를 따로 빼는 것이 좋겠네요. 독립적인 클래스로 따로 빼서 class A; class C; 두 전방선언을 하고 진행해보니 아무 문제 없네요!





