[C++] friend 선언(클래스, 함수)

2024. 4. 3. 15:22Programming Language/C++

friend 선언 - 클래스

• 클래스에 friend 선언을 하면 private 멤버에 접근할 수 있다.

애초에 private의 목적이 외부에 공개하지 않는 것이기 때문에 웬만하면 friend를 사용하지 않는 게 좋다.
접근하기 불편하다고 friend 선언이나 public 선언을 하면 어디에서든지 접근하여 사용할 수 있어서 유지보수가 힘들어진다.
따라서 데이터를 주고받을 일이 많지 않다면 멤버는 private으로 감추고 멤버 함수를 통해서만 접근할 수 있도록 막아주는 방법이 좋다.

▷ 예시

#include <iostream>

using std::cout;
using std::endl;

class A; // A 클래스 미리 선언

class B {
private:
    int bi;
    friend class A; // A 클래스는 B 클래스의 private 멤버에 직접 접근할 수 있다.
public:
    B(int value) : bi(value) {}  // bi 초기화
};

class A {
private:
    int ai;
public:
	A(int value = 0) : ai(value) {}

    void Add(const B& b) {
        ai += b.bi; // B 클래스의 private 멤버 bi에 접근
    }

    void Print() const {
        cout << "A::ai = " << ai << endl;
    }
};

int main() {
    A a(5);
    B b(10);

    a.Add(b); // A 객체에 B 객체의 bi 값을 더하기
    a.Print(); // 결과 출력

    return 0;
}

▽ 출력 결과

15

B 클래스가 `friend class A`로 friend 선언을 했다.

B 클래스 : "A 클래스는 내 친구야."

A 클래스는 B 클래스의 private 멤버에 직접 접근할 수 있다.

※ 헷갈림 주의!

B가 A를 친구라고 선언해도 A는 B를 친구로 받아들이지 않았다.

상대방(B)이 일진처럼 일방적으로 친구라고 하면서 내(A) 사적인 것을 가져갈 수 없듯이 B는 A의 private 멤버에 접근할 수 없다.

 

만약 A와 B 쌍방향으로 private 멤버를 공유하고 싶다면?

① 각 멤버 파트를 얻어올 수 있게 하는 `get()`을 제공한다.

② 모든 클래스 사이에서 서로 friend 선언한다.


friend 선언 - 함수

• 다른 클래스 안의 함수를 friend 선언으로 접근할 수 있다.

class A;  // A 클래스의 이름을 미리 알림

class B  // A 연산을 정의하는 클래스
{
private:
    int opcnt;
public:
    B() : opcnt(0) {}
    A Add(const A&, const A&);  // 클래스 함수를 선언만 하므로 매개변수의 이름을 생략할 수 있다.
};

class A
{
private:
    int x;
    int y;
public:
    A() : x(0), y(0) {}                      // 기본 생성자
    A(int xVal, int yVal) : x(xVal), y(yVal) {} // 매개변수 생성자
    
    friend A B::Add(const A&, const A&);  // B 안의 함수를 friend 선언하여 접근
    friend void Print(const A&);  // 전역 함수 Print()에 friend 선언
};

A B::Add(const A& pnt1, const A& pnt2)
{
    opcnt++;
    return A(pnt1.x + pnt2.x, pnt1.y + pnt2.y);
}

void Print(const A& pnt) {
    cout << "x: " << pnt.x << ", y: " << pnt.y << endl;
}

int main(void)
{
    A a1(1, 2);
    A a2(2, 4);
    B b;

    Print(b.Add(a1, a2));

    return 0;
}