friend 함수, 클래스 올바르게 사용하기
2019. 11. 17. 11:45ㆍPL/C++
클래스 간 상호작용을 위해서 friend 키워드가 가끔 사용된다. 캡슐화에 위배되는 사항이라 사용은 지양되지만 실제로 연산자 오버로딩 등 절대적으로 필요한 부분이 있다
다음 코드는 클래스 A에 private 멤버에 접근하려고하니 오류가 발생한 것이다
#include <iostream>
using namespace std;
class A {
private:
int m_value = 1;
};
void printA(A &a) {
cout << a.m_value << '\n'; // 컴파일 오류
}
int main(void) {
A a;
printA(a);
return 0;
}
friend 함수를 정의해서 'printA는 우리와 친구다'라고 A class 안에서 정의할 수 있다
#include <iostream>
using namespace std;
class A {
private:
int m_value = 1;
friend void printA(A &);
};
void printA(A &a) {
cout << a.m_value << '\n';
}
int main(void) {
A a;
printA(a);
return 0;
}
클래스 하나를 더 확장을 해보자. 그런데 다시 a.m_value 쪽에서 오류가 발생한다
#include <iostream>
using namespace std;
class A {
private:
int m_value = 1;
friend void printA(A &, B &);
};
class B {
private:
int m_value = 2;
friend void printA(A &, B &);
};
void printA(A &a, B &b) {
// a.m_value만 오류
cout << a.m_value << ' ' << b.m_value << '\n';
}
int main(void) {
A a;
B b;
printA(a, b);
return 0;
}
이유는 class A는 class B 앞에 선언되어 있기 때문에 B의 존재를 알 수가 없기에 식별자 오류를 발생시켰다. 따라서 함수 프로토타입처럼 전방선언을 해줘야만 A는 B의 존재를 이때서야 알게 된다
class B;
class A {
...
};
friend class는 다음과 같이 클래스를 friend 선언을 통해서 나타낸다
#include <iostream>
using namespace std;
class B;
class A {
private:
int m_value = 1;
friend class B;
};
class B {
private:
int m_value = 2;
public:
void doSomething(A &a) {
cout << a.m_value << '\n';
}
};
int main(void) {
A a;
B b;
b.doSomething(a);
return 0;
}
그리고 클래스 전방 선언을 할지라도 그 안의 멤버함수와, 변수의 내용은 알지 못한다.
아래 코드에서는 class B를 알지만, doSomething이라는 멤버함수가 있는지까지는 모른다
#include <iostream>
using namespace std;
class B;
class A {
private:
int m_value = 1;
friend void B::doSomething(A &a);
};
class B {
private:
int m_value = 2;
public:
void doSomething(A &a) {
cout << a.m_value << '\n';
}
};
그러면 class B를 올려볼까?
#include <iostream>
using namespace std;
class A;
class B {
private:
int m_value = 2;
public:
void doSomething(A &a) {
cout << a.m_value << '\n';
}
};
class A {
private:
int m_value = 1;
friend void B::doSomething(A &a);
};
그래도 오류가 발생한다. 왜냐하면 이제는 class A가 전방선언이 되어있다고 하지만, A의 멤버변수인 m_value에 대해서는 알지 못한다. 따라서 보통 이러한 경우에는 class A, B가 모두 선언된 후 밑에다 작성을 해야만 한다
#include <iostream>
using namespace std;
class A;
class B {
private:
int m_value = 2;
public:
void doSomething(A &);
};
class A {
private:
int m_value = 1;
friend void B::doSomething(A &a);
};
void B::doSomething(A &a) {
cout << a.m_value << '\n';
}
int main(void) {
A a;
B b;
b.doSomething(a);
return 0;
}
'PL > C++' 카테고리의 다른 글
컴파일 에러와 런타임 에러 (0) | 2019.11.18 |
---|---|
for문 증감부분에서의 ++i와 i++의 차이 (0) | 2019.11.17 |
new 연산자를 이용한 2차원 배열 할당 (0) | 2019.11.16 |
가상 소멸자가 필요한 이유 (0) | 2019.11.16 |
큐 연결리스트로 구현하기 (0) | 2019.11.15 |