class Tv
{
public:
freind class Remote;
bool volup();
private:
int state;
int channel;
}
class Remote
{
private:
int mode;
public:
bool volup(Tv & t) { return t.volup(); }
void set_chan(Tv & t, int c) { t.channel = c; }
}
- Tv의 private 멤버에 직접 접근가능한 Remote 메서드 set_chan
- 프렌드 자격을 부여할 필요가 있는 것은 private에 직접 접근할 필요가 있는 메서드
- Remote::set_chan()을 Tv클래스에 대해 프렌드로 만드는 방법은, Tv클래스 선언 안에 그것을 프렌드로 선언하는 것
- Tv의 private 멤버에 접근할 수 있는 메서드를 Remote에서 많이 만들어도 모두 접근할 수 있다. Remote 자체가 friend이기 때문
class Tv
{
public:
freind void Remote::set_chan(Tv & t, int c); //프렌드
bool volup();
private:
int state;
int channel;
}
- 선언과 정의를 배치하는 순서를 신경써야한다.
- 저 프렌드 선언이 나오기 전에 Remote 정의를 미리 알고 있어야 한다.
- 하지만 Remote클래스 내부에 있는 메서드가 Tv의 객체를 필요한다 그렇게 되면 또 Tv 정의가 앞에 있어야한다.
- 순환 종속을 피하기 위해서 사전선언을 사용한다.
//맞는 선언
class Tv; //사전 선언
class Remote { ... };
class Tv { ... };
//틀린 선언
class Remote; //사전 선언
class Tv { ... };
class Remote { ... };
- 밑의 내용이 틀린 선언인 이유는 Tv에서 set_chan()을 프렌드로 갖고 있으면 그 때에 Remote의 선언을 알고 있어야한다.
- 맞는 선언도 Remote안의 Tv의 메서드를 호출하는 메서드가 있다. 이 시점에서도 컴파일러가 Tv클래스의 선언을 알고 있어야한다.
- 하지만 Tv의 선언은 Remote선언의 뒤에 와야만 한다. 이 문제의 해결책은 Remote를 메서드 선언으로 제한하고 실제 정의들은 Tv 클래스 뒤에 두는 것이다.
Remote의 메서드 선언 (선택된 메서드만을 friend로 갖는 프렌드)
class Tv; //사전 선언
class Remote
{
private:
int mode;
public:
bool volup(Tv & t); //메서드 선언 (원형만 선언해놓는다.)
void set_chan(Tv & t, int c);
}
class Tv
{
public:
freind void Remote::set_chan(Tv & t, int c);
bool volup();
private:
int state;
int channel;
}
inline bool Remote::volup(Tv & t) { return t.volup(); }
inline void Remote::set_chan(Tv & t, int c) { t.channel = c; }
- 이 경우 set_chan만 Tv에 있는 private멤버 권한을 가지고 있게 된다.
상호 프렌드
class Tv
{
freind class Remote;
public:
bool buzz(Remote & r);
private:
int state;
int channel;
}
class Remote
{
friend class Tv;
public:
bool volup(Tv & t) { t.volup(); }
private:
int mode;
}
inline bool buzz(Remote & r) { ... }
- 서로의 클래스를 프렌드로 한다.
- Remote 선언이 Tv 선언 뒤에 나오기 때문에 Tv 객체를 사용하는 volup()을 Remote 클래스 선언 안에 정의할 수 있다.
- 그러나 Tv의 buzz() 정의는 Tv선언의 밖에 해야한다. Remote보다 앞에서 선언이 되었기 때문이다.
공유 프렌드
class Analyzer; //후에 참조를 불러오기에 후에 선언되는 Analyzer를 사전선언한다.
class Probe
{
friend void sync(Analyzer & a, const Probe & p); //a를 p에 맞춘다.
friend void sync(Probe & p, const Analyzer & a); //p를 a에 맞춘다.
}
class Analyzer
{
friend void sync(Analyzer & a, const Probe & p); //a를 p에 맞춘다.
friend void sync(Probe & p, const Analyzer & a); //p를 a에 맞춘다.
}
void sync(Analyzer & a, const Probe & p); { ... }
void sync(Probe & p, const Analyzer & a); { ... }
- 내부 장치를 서로 일치시키고 싶게 만든다면 이런 식으로 다른 두 클래스의 private에 접근한다.
'C++ > Basic' 카테고리의 다른 글
[C++] 예외 처리 (2) | 2021.07.26 |
---|---|
[C++] 내포 클래스 (0) | 2021.07.23 |
[C++] 템플릿 클래스 (0) | 2021.07.19 |
[C++] 다중 상속과 가상 기초 클래스 (0) | 2021.07.14 |
[C++] public 다형 상속 (0) | 2021.07.06 |