C++ 프렌드 함수와 프렌드 클래스: 접근 제어 마스터하기
C++ 프렌드 함수와 프렌드 클래스: 접근 제어 마스터하기
이 튜토리얼에서는 명확한 예제와 함께 C++에서 프렌드 함수와 프렌드 클래스를 선언하고 사용하는 방법을 보여줍니다.
소개
데이터 은닉은 객체 지향 프로그래밍의 초석으로, 외부 코드가 클래스의 private 멤버에 직접 접근하는 것을 방지합니다. Protected 멤버는 파생 클래스에서만 보이며 외부에서는 접근할 수 없습니다.
다음 예제를 살펴보세요:
class MyClass {
private:
int member1;
};
int main() {
MyClass obj;
// 오류! 여기서 private 멤버에 접근할 수 없음.
obj.member1 = 5;
}
이러한 제한에도 불구하고 C++은 일반적인 접근 제어를 우회해 클래스의 private 및 protected 데이터에서 작동할 수 있는 프렌드 함수라는 메커니즘을 제공합니다.
프렌드 클래스는 비슷한 개념으로, 전체 클래스가 프렌드 역할을 할 수 있게 합니다. 두 기능 모두 신중하게 사용하면 캡슐화를 해치지 않으면서 유연성을 높이는 강력한 도구입니다.
C++ 프렌드 함수
프렌드 함수는 클래스의 private 및 protected 멤버를 읽고 수정할 수 있습니다. 클래스 정의 내에서 friend 키워드로 선언합니다.
class ClassName {
// ...
friend returnType functionName(arguments);
// ...
}
예제 1: 기본 프렌드 함수
// C++ 프렌드 함수 작동 예제
#include <iostream>
using namespace std;
class Distance {
private:
int meter;
// 프렌드 함수 선언
friend int addFive(Distance);
public:
Distance() : meter(0) {}
};
// 프렌드 함수 정의
int addFive(Distance d) {
// 프렌드 함수에서 private 멤버 접근
d.meter += 5;
return d.meter;
}
int main() {
Distance D;
cout << "Distance: " << addFive(D);
return 0;
}
출력
Distance: 5
addFive() 함수는 프렌드 함수가 private meter 필드에 자유롭게 접근할 수 있음을 보여줍니다. 이 예제는 단순하지만 프렌드 함수의 핵심 아이디어를 잘 보여줍니다.
예제 2: 두 클래스에 대한 연산
// 프렌드 함수를 사용해 두 다른 클래스의 멤버 더하기
#include <iostream>
using namespace std;
// 전방 선언
class ClassB;
class ClassA {
public:
// numA를 12로 초기화하는 생성자
ClassA() : numA(12) {}
private:
int numA;
// 프렌드 함수 선언
friend int add(ClassA, ClassB);
};
class ClassB {
public:
// numB를 1로 초기화하는 생성자
ClassB() : numB(1) {}
private:
int numB;
// 프렌드 함수 선언
friend int add(ClassA, ClassB);
};
// 두 클래스의 멤버에 접근
int add(ClassA objectA, ClassB objectB) {
return (objectA.numA + objectB.numB);
}
int main() {
ClassA objectA;
ClassB objectB;
cout << "Sum: " << add(objectA, objectB);
return 0;
}
출력
Sum: 13
이 프로그램에서 ClassA와 ClassB 모두 add() 함수를 프렌드로 선언합니다. 이로써 함수가 두 클래스의 private 데이터에 접근해 numA와 numB의 합을 구할 수 있습니다.
ClassA의 프렌드 선언이 정의되기 전인 ClassB를 참조함을 알 수 있습니다. 전방 선언 class ClassB;가 이 의존성을 해결합니다.
C++ 프렌드 클래스
전체 클래스를 프렌드로 선언하면 그 클래스의 모든 멤버 함수가 호스트 클래스의 private 및 protected 멤버에 접근할 수 있게 됩니다. 문법은 간단합니다:
class ClassB;
class ClassA {
// ClassB는 ClassA의 프렌드 클래스
friend class ClassB;
// ...
}
class ClassB {
// ...
}
ClassB가 ClassA의 프렌드이므로 ClassB 내부의 어떤 메서드도 ClassA의 private 데이터를 자유롭게 읽거나 수정할 수 있습니다. 역은 성립하지 않습니다; ClassA가 ClassB를 프렌드로 선언하지 않는 한 ClassB의 private 멤버에 접근할 수 없습니다.
예제 3: 프렌드 클래스 실전
// C++ 프렌드 클래스 작동 예제
#include <iostream>
using namespace std;
// 전방 선언
class ClassB;
class ClassA {
private:
int numA;
// 프렌드 클래스 선언
friend class ClassB;
public:
// numA를 12로 초기화하는 생성자
ClassA() : numA(12) {}
};
class ClassB {
private:
int numB;
public:
// numB를 1로 초기화하는 생성자
ClassB() : numB(1) {}
// ClassA의 numA와 ClassB의 numB를 더하는 멤버 함수
int add() {
ClassA objectA;
return objectA.numA + numB;
}
};
int main() {
ClassB objectB;
cout << "Sum: " << objectB.add();
return 0;
}
출력
Sum: 13
ClassB의 add() 메서드는 ClassA가 ClassB를 프렌드로 선언했으므로 ClassA의 private 멤버 numA에 접근할 수 있습니다. 이 예제는 프렌드 클래스가 일반적인 접근 규칙에 예외를 두면서도 캡슐화를 유지하며 긴밀한 협력을 가능하게 함을 보여줍니다.
전반적으로 프렌드 함수와 프렌드 클래스는 클래스 경계 간에 제어된 접근이 필요할 때 유용한 C++ 도구입니다. 설계상 이점이 있을 때만 아껴서 사용하세요.