reference:
- "명품 C++ 프로그래밍" / 황기태 / 생능출판사
- http://www.tcpschool.com/cpp/cpp_encapsulation_friend
클래스 내부 코드 외부에서 객체의 private 멤버에는 public 멤버 함수를 통해서만 접근할 수 있다(캡슐화).
하지만 경우에 따라서는 해당 객체의 멤버 함수 외의 함수도 private 멤버에 접근해야하는 상황이 발생한다.
이럴 때마다 private 멤버에 접근하기 위한 새로운 public 멤버 함수를 작성하는 것에 번거롭다면 프렌드(friend)라는 접근 제어 키워드를 사용하여 지정한 대상에 한해 해당 객체의 모든 멤버에 접근 권한을 부여해준다.
=> "클래스의 멤버로 선언하기에는 무리가 있고, 클래스의 모든 멤버를 자유롭게 접근할 수 있는 일부 외부 함수 작성 시 사용"
이 friend 키워드는 (1) 전역 함수, (2) 멤버 함수, (3) 클래스의 세 가지 형태로 사용할 수 있다.
(1) 전역 함수: 클래스 외부에 선언된 전역 함수
(2) 다른 클래스의 멤버 함수: 다른 클래스의 특정 멤버 함수
(3) 다른 클래스의 모든 멤버 함수

source: "명품 c++ 프로그래밍" / 황기태 / 생능출판사
friend class_name func_name(매개변수 목록);
위와 같이 선언된 프렌드 함수는 클래스 선언부에 그 원형이 포함되지만, 클래스의 멤버 함수는 아니다.
다만 멤버 함수와 같은 접근 권한을 가지게 된다.
// Rect 클래스가 선언되기 전에 equals 함수에서 먼저 참조되기에 컴파일 오류를 막기위한 선언문
class Rect;
// equals() 전역 함수 선언
bool equals(Rect r, Rect s);
class Rect {
private:
int width, height;
public:
Rect(int width, int heght) {
this->width = width;
this->height = heght;
}
// 전역 함수 equals()를 프렌드로 선언
friend bool equals(Rect r, Rect s);
};
bool equals(Rect r, Rect s) {
if (r.width == s.width && r.height == s.height)
return true;
else
return false;
}
class Rect;
class RectManager {
public:
bool equals(Rect r, Rect s);
};
class Rect {
private:
int width, height;
public:
Rect(int width, int heght) {
this->width = width;
this->height = heght;
}
// RectManager 클래스의 equals() 멤버를 프렌드로 선언
friend bool RectManager::equals(Rect r, Rect s);
};
bool RectManager::equals(Rect r, Rect s) {
if (r.width == s.width && r.height == s.height)
return true;
else
return false;
}
class Rect;
class RectManager {
public:
bool equals(Rect r, Rect s);
void copy(Rect& dest, Rect& src);
};
class Rect {
private:
int width, height;
public:
Rect(int width, int heght) {
this->width = width;
this->height = heght;
}
// RectManager 클래스를 프렌드 함수로 선언
friend RectManager;
};
bool RectManager::equals(Rect r, Rect s) {
if (r.width == s.width && r.height == s.height)
return true;
else
return false;
}
void RectManager::copy(Rect& dest, Rect& src) {
dest.width = src.width;
dest.height = src.height;
}