티스토리 뷰

반응형

🔐 C++ friend 완전 이해: 함수, 클래스, 멤버 함수 – 각각 언제, 왜, 어떻게?

C++에서 private 멤버는 철저히 감춰져 있어서, 클래스 외부에서는 접근할 수 없습니다.
하지만 외부 함수나 다른 클래스가 그 내부에 꼭 접근해야 하는 경우, 이 제한을 예외적으로 풀어줄 필요가 있습니다.

이때 사용하는 것이 바로 friend 키워드입니다.
단, 남용하면 객체 간 결합도가 높아지므로 정확한 용도와 상황을 이해한 뒤에 사용해야 합니다.



✅ friend 함수 – 외부 함수에게 클래스 내부 비밀을 보여줘야 할 때

🚨 문제: 외부 함수가 클래스의 private 멤버에 접근해야 한다

다음 예제를 보세요. 외부 함수 printWidthBox 클래스의 width에 접근하려고 합니다.
class Box {
private:
    int width;
public:
    Box(int w) : width(w) {}
};

int printWidth(Box b) {
    return b.width; // ❌ 오류 발생: private 접근 불가
}
error: ‘int Box::width’ is private within this context

🧠 원인:

  • printWidth는 클래스 외부 함수이므로 Box의 private 멤버에 접근할 권한이 없습니다.

💡 해결: printWidth를 Box 클래스의 친구로 등록

#include <iostream>

class Box {
private:
    int width;

public:
    Box(int w) : width(w) {}

    // 외부 함수 printWidth를 friend로 지정
    friend int printWidth(Box b);
};

// friend 함수 정의: private 멤버에 접근 가능
int printWidth(Box b) {
    std::cout << "Box의 너비는 " << b.width << "입니다." << std::endl;
    return b.width;
}

int main() {
    Box b(7);
    int w = printWidth(b);
    std::cout << "출력된 너비: " << w << std::endl;
    return 0;
}

✅ 출력 결과

Box의 너비는 7입니다.
출력된 너비: 7

📌 코드 이후 설명

  • friend 키워드를 사용해 printWidth 함수에게 Box의 private 멤버 접근 권한을 줬습니다.
  • 외부 함수인데도 내부 정보(width)를 읽을 수 있습니다.
  • 입출력 함수, 디버그 함수처럼 클래스 외부에서 객체 정보를 읽는 함수에 적합합니다.



✅ friend 클래스 – 다른 클래스가 이 클래스의 내부 전부를 봐야 할 때

🚨 문제: A 클래스가 B 클래스의 private 멤버를 자주 읽어야 한다

class Engine {
private:
    int temperature;
public:
    Engine() : temperature(90) {}
};

class Car {
public:
    void showTemp(Engine e) {
        std::cout << e.temperature << std::endl; // ❌ 오류
    }
};
error: ‘int Engine::temperature’ is private within this context

🧠 원인:

  • Car 클래스는 Engine 클래스의 내부에 접근할 권한이 없습니다.

💡 해결: Car 전체를 Engine의 friend로 지정

#include <iostream>

class Car; // 전방 선언

class Engine {
private:
    int temperature;

public:
    Engine() : temperature(90) {}

    // Car 클래스를 friend로 지정
    friend class Car;
};

class Car {
public:
    void showTemp(Engine e) {
        std::cout << "엔진 온도는 " << e.temperature << "도입니다." << std::endl;
    }
};

int main() {
    Engine e;
    Car c;
    c.showTemp(e);
    return 0;
}

✅ 출력 결과

엔진 온도는 90도입니다.

📌 코드 이후 설명

  • Car 클래스 전체가 Engine 클래스의 친구로 지정되었기 때문에 모든 멤버 함수는 Engine의 private 멤버에 자유롭게 접근할 수 있습니다.
  • 구성 관계, 제어 관계처럼 전체 클래스 간의 협력이 필요한 경우에 friend 클래스를 사용합니다.
  • 남용하면 클래스 간 의존성이 심해지므로 반드시 관계가 명확할 때만 써야 합니다.



✅ friend 멤버 함수 – 특정 멤버 함수만 접근하게 하고 싶을 때

🚨 문제: A 클래스의 특정 멤버 함수만 B 클래스의 private 멤버에 접근하고 싶다

class Engine {
private:
    int rpm;
public:
    Engine() : rpm(3000) {}
};

class Car {
public:
    void debug(Engine e) {
        std::cout << e.rpm << std::endl; // ❌ 오류
    }
};
error: ‘int Engine::rpm’ is private within this context

🧠 원인:

  • Car::debug()Engine의 내부를 보고 싶지만 접근 권한이 없습니다.

💡 해결: 특정 멤버 함수만 friend로 지정

#include <iostream>

class Car; // 전방 선언

class Engine {
private:
    int rpm;

public:
    Engine() : rpm(3000) {}

    // Car 클래스의 특정 멤버 함수만 friend로 지정
    friend void Car::debug(Engine e);
};

class Car {
public:
    void debug(Engine e) {
        std::cout << "엔진 회전수: " << e.rpm << "rpm" << std::endl;
    }
};

int main() {
    Engine e;
    Car c;
    c.debug(e);
    return 0;
}

✅ 출력 결과

엔진 회전수: 3000rpm

📌 코드 이후 설명

  • friend void Car::debug(Engine e);Car 클래스의 특정 함수 하나만 Engine의 내부에 접근할 수 있도록 합니다.
  • 전체 Car 클래스에 권한을 주지 않고, 정밀하게 한 함수만 허용하므로 안전성이 더 높습니다.
  • 디버깅, 테스트, 로깅 등 특정 함수만 예외 접근이 필요할 때 사용합니다.



🧠 정리: 언제 어떤 friend를 써야 할까?

상황 쓰는 friend 종류 이유
외부 함수 하나가 객체 내부를 접근해야 함 friend 함수 입출력 함수, 계산 함수 등
특정 클래스 전체가 객체 내부에 접근해야 함 friend 클래스 구조적으로 긴밀하게 협력해야 할 때
특정 함수 하나만 접근해야 함 friend 멤버 함수 디버깅, 로깅 함수에만 예외 허용



🎯 마무리

C++의 friend정보 은닉을 지키면서도 예외적 협력이 필요할 때 사용하는 강력한 도구입니다.

하지만 설계 의도를 명확히 하지 않으면 객체 간 결합도가 높아져 코드가 복잡해질 수 있습니다.

  • 반드시 문제와 이유가 명확할 때만 사용하세요.
  • 함수 / 클래스 / 멤버 함수 중 어떤 것이 적절한지도 상황에 맞춰 판단해야 합니다.
반응형
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/05   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
글 보관함