1. friend 개념
- 클래스의 멤버 함수는 아니지만, 해당 클래스의 private 멤버에 접근할 수 있도록 하는 도구
- 형태: friend 함수 / friend 클래스 / friend 연산자 오버로딩
** friend 함수는 멤버함수가 아니므로 .이나 ->를 통해 호출 불가능
** 그러나 private 멤버변수에 대해, 멤버함수와 동등한 접근 권한을 가짐
* 주의
- friend는 비공개 멤버에 대한 접근을 허용하는 기능이므로 남용하지 않는 것이 안전
- 클래스 간의 관계를 더 명확하게 구성하고, 필요한 경우에만 friend를 사용할 것
2. friend를 사용하는 주요 경우
2-1. friend 함수: '함수'를 클래스의 freind로 선언
해당 함수는 클래스의 멤버 함수가 아니지만 클래스의 private 멤버에 접근할 수 있게 됨
class MyClass {
private:
int privateData;
public:
MyClass(int data) : privateData(data) {}
friend void friendFunction(MyClass obj); // 'friend 함수' 선언};
→ friendFunction 함수는 MyClass 클래스 '외부'에서 정의되어 있음
→ 외부에서 정의된 함수가 MyClass의 멤버 변수에 접근하려면, MyClass 클래스 내부에 그것의 원형이 선언되어 있어야 함
→ 더 원하는 친구가 직접 발품 팔기.~! ㅎㅎ
2-2. friend 클래스: '클래스'를 다른 클래스의 friend로 선언
다른 클래스의 private 멤버에 접근할 수 있게 됨
class FriendClass {
private:
int secretData;
public:
FriendClass(int data) : secretData(data) {}};
class MyClass {
private:
int privateData;
public:
MyClass(int data) : privateData(data) {}
friend class FriendClass; // FriendClass는 MyClass의 private member에 접근할 수 있음};
→ 마찬가지로, FriendClass 역시 MyClass '외부'에 정의되어 있음
2-3. friend 함수와 friend 클래스를 모두 사용하는 경우
#include <iostream>
class FriendClass;
class MyClass {
private:
int privateData;
public:
MyClass(int data) : privateData(data) {}
// FriendClass를 friend 클래스로 선언
friend class FriendClass;
void PrintPrivateData() {
std::cout << "MyClass privateData: " << privateData << std::endl;
}
};
class FriendClass {
private:
int secretData;
public:
FriendClass(int data) : secretData(data) {}
void AccessMyClassPrivateData(MyClass& obj) {
std::cout << "FriendClass accessing MyClass privateData: " << obj.privateData << std::endl;
}
};
int main() {
MyClass myObj(42);
FriendClass friendObj(100);
myObj.PrintPrivateData(); // MyClass의 멤버 함수를 통한 privateData 접근
friendObj.AccessMyClassPrivateData(myObj); // FriendClass를 통한 privateData 접근
return 0;
}
연산자 오버로딩에서 friend가 사용되는 사례
- 어떤 클래스에 이항 연산자를 오버로딩할 경우 friend가 필요한 경우 발생함 (*이항 연산자 : 두 개의 피연산자를 요구하는 연산자)
(1) friend만을 이용해서 연산자 오버로딩 하는 경우
(단, 입력 매개변수가 'int * 클래스' 순서를 지켜야 함)
time.h
#include<iostream>
using namespace std;
#ifndef FIRE_C_TIME_H
#define FIRE_C_TIME_H
class Time{
private:
int hours;
int mins;
public:
Time();
Time(int, int);
void show();
~Time();
friend Time operator*(int n, Time& t); //friend를 활용한 연산자 오버로딩
};
#endif //FIRE_C_TIME_H
time_func.cpp
#include "time.h"
Time::Time(){
hours = 0;
mins = 0;}
Time::Time(int h, int m){
hours = h;
mins = m;}
void Time::show(){
cout << hours << "시간 " << mins << "분" << endl;}
Time::~Time(){}
// friend 통해 선언한 함수를 정의할 때
// 그것은 멤버함수가 아니므로 클래스 귀속 :: 표시도 하지 않고, friend를 명시하지도 않음
// 매개변수 입력 순서 중요
Time operator*(int n, Time& t){ //n*t로 해석됨
Time result;
long resultMin = t.hours * n * 60 + t.mins * n;
result.hours = resultMin / 60;
result.mins = resultMin % 60;
return result;
}
main.cpp
#include "time.h"
#include "time_func.cpp"
//c++ friend: public 이외에도 private 멤버변수에 접근할 수 있는 또 다른 방법
int main(){
Time t1(1, 20);
Time t2;
Time t3;
t2 = 3 * t1; //순서 바뀌면 안 됨
t2.show();
return 0;
}
(2) 사실.. 굳이 friend 쓰지 않아도 구현됨 (단, 입력 매개변수가 '클래스 * int' 순서를 지켜야 함)
time.h
#include<iostream>
using namespace std;
#ifndef FIRE_C_TIME_H
#define FIRE_C_TIME_H
class Time{
private:
int hours;
int mins;
public:
Time();
Time(int, int);
void show();
~Time();
Time operator*(int n);
};
#endif //FIRE_C_TIME_H
time_func.cpp
#include "time.h"
Time::Time(){
hours = 0;
mins = 0;}
Time::Time(int h, int m){
hours = h;
mins = m;}
void Time::show(){
cout << hours << "시간 " << mins << "분" << endl;}
Time::~Time(){}
// friend를 사용하지 않고 클래스의 멤버함수로 정의할 때
Time Time::operator*(int n){
Time result;
long resultMin = hours * n * 60 + mins * n;
result.hours = resultMin / 60;
result.mins = resultMin % 60;
return result;
}
main.cpp
#include "time.h"
#include "time_func.cpp"
int main(){
Time t1(1, 20);
Time t2;
t2 = t1 * 4;
t2.show();
return 0;
}
//5시간 20분
(3) 두 개의 입력 매개변수 순서를 자유롭게 하고 싶을 때 ~!
→ 그러면 friend 이용하는 경우와 이용하지 않는 경우 모두 활용하면 됨 (단순..)
time.h
#include<iostream>
using namespace std;
#ifndef FIRE_C_TIME_H
#define FIRE_C_TIME_H
class Time{
private:
int hours;
int mins;
public:
Time();
Time(int, int);
void show();
~Time();
Time operator*(int n); //멤버함수
friend Time operator*(int, Time&); //friend 함수
};
#endif //FIRE_C_TIME_H
time_func.cpp
#include "time.h"
Time::Time(){
hours = 0;
mins = 0;}
Time::Time(int h, int m){
hours = h;
mins = m;}
void Time::show(){
cout << hours << "시간 " << mins << "분" << endl;}
Time::~Time(){}
// friend를 사용하지 않고 클래스의 멤버함수로 정의할 때
Time Time::operator*(int n){
Time result;
long resultMin = hours * n * 60 + mins * n;
result.hours = resultMin / 60;
result.mins = resultMin % 60;
return result;
}
// friend 통해 선언한 함수를 정의할 때
// 그것은 멤버함수가 아니므로 클래스 귀속 :: 표시도 하지 않고, friend를 명시하지도 않음
Time operator*(int n, Time& t){
return t*n;
}
main.cpp
#include "time.h"
#include "time_func.cpp"
int main(){
Time t1(1, 20);
Time t2;
t2 = t1 * 4;
t2.show();
t2 = 4 * t1;
t2.show();
return 0;
}
/*5시간 20분
5시간 20분*/