[C++] 프렌드

cheon2308
|2023. 12. 5. 19:32
728x90

황기태 저자의 명품 C++ Programming 개정판을 읽고 학습한 내용을 정리한 포스트입니다!

https://search.shopping.naver.com/book/catalog/32436115747

 

C++ Programming : 네이버 도서

네이버 도서 상세정보를 제공합니다.

search.shopping.naver.com

프렌드

  • 클래스 내에 friend 키워드로 선언된 외부 함수를 프렌드 함수(friend function)라고 부르며, 마치 클래스의 멤버인것처럼 클래스의 모든 변수나 함수에 접근 가능하지만 ! 실질적 멤버가 아니므로 상속되지는 않는다.

필요성 & 선언

 

 클래스 멤버 함수로는 적합하지 않지만 private, protected 멤버를 접근해야 하는 특별한 경우, 이 함수를 외부 함수로 작성하고 프렌드로 선언하며, 가장 유용하게 사용되는 대표적인 경우가 연산자 함수이다.

 선언하는 방법은 아래 3가지가 있다.

  1. 클래스 외부에 작성된 함수를 프렌드로 선언
  2. 다른 클래스의 멤버 함수를 프렌드로 선언
  3. 다른 클래스의 모든 멤버 함수를 프렌드로 선언

프렌드 함수 선언
class Rect {
	....
	friend bool equals(Rect r, Rect s); // 함수 equals()를 프렌드 함수로 선언
};
#include <iostream>
using namespace std;

class Rect; // forward decalaration. 이 라인이 없으면, 다음 라인에서 Rect를 참조하는 전방 참조(forward reference) 문제 발생
bool equals(Rect r, Rect s); // equals() 함수 선언

class Rect { // Rect 클래스 선언
	int width, height;
public:
	Rect(int width, int height)  { 	this->width = width; this->height = height;	}
	friend bool equals(Rect r, Rect s); //프렌드 함수 선언
};

bool equals(Rect r, Rect s) { // 외부 함수
	if(r.width == s.width && r.height == s.height) return true; // equals() 함수는 private 속성을 가진 width, height에 접근할 수 있다.
	else return false;
}

int main() {
	Rect a(3,4), b(4,5);
	if(equals(a, b)) cout << "equal" << endl;
	else cout << "not equal" << endl;
}

 

Tip!!! 전방 참조(forward reference) 문제 해결을 위한 전방 선언(forward declaration)

  • C++에서는 아래와 같이 변수나 함수, 클래스의 이름을 먼저 선언한 후 그 이름(Identifier)을 참조(사용)하는 backward reference가 원칙
class Rect { // Rect 이름선언
	...
};
int main() {
	Rect rect; // 선언된 Rect 사용. backward reference
}
  • but, 가끔 뒤에서 선언되는 이름을 미리 참조(사용)하는 경우가 발생하는데 이를 전방 참조라 부른다.
  • 컴파일러 입장에서는 아직 선언되지 않는 이름을 참조(사용)하므로 forward reference를 컴파일 오류로 처리한다.
bool equals(Rect r, Rect s); // equals() 함수 선언

class Rect { // Rect 클래스 선언
	int width, height;
public:
	Rect(int width, int height)  { 	this->width = width; this->height = height;	}
	friend bool equals(Rect r, Rect s); //프렌드 함수 선언
}; // 컴파일 오류 발생
class Rect; // forward decalaration. 이 라인이 없으면, 다음 라인에서 Rect를 참조하는 전방 참조(forward reference) 문제 발생
bool equals(Rect r, Rect s); // equals() 함수 선언

 

프렌드 멤버 선언
  • 다른 클래스의 멤버 함수를 클래스의 프렌드 함수로 선언 가능
class Rect {
	friend bool RectManager::equals(Rect r, Rect s); // RectManager의 equals() 멤버 함수를 프렌드로 초대
};

 

프렌드 클래스 선언
  • 다른 클래스의 모든 멤버 함수를 클래스의 프렌드 함수로 한 번에 선언할 수 잇다.
class Rect {
	.....
	friend RectManager; // RectManager 클래스의 모든 함수를 프렌드로 초대
};
  • RectManager 클래스 전체를 Rect 클래스의 프렌드로 선언하는 사례이다.
  • RectManager 클래스에는 두 개의 멤버 함수가 있으며, 이들은 모두 Rect 클래스의 private 멤버를 자유롭게 접근한다.
#include <iostream>
using namespace std;

class Rect;

class RectManager { // RectManager 클래스 선언
public:
	bool equals(Rect r, Rect s);
	void copy(Rect& dest, Rect& src);
};

class Rect { // Rect 클래스 선언
	int width, height;
public:
	Rect(int width, int height)  { this->width = width; this->height = height; }
	friend RectManager; // RectManager 클래스의 모든 함수를 프렌드 함수로 선언
};

bool RectManager::equals(Rect r, Rect s) { // r과 s가 같으면 true 리턴
	if(r.width == s.width && r.height == s.height) return true; 
	else return false;
}

void RectManager::copy(Rect& dest, Rect& src) { // src를 dest에 복사
	dest.width = src.width;  dest.height = src.height;
}

int main() {
	Rect a(3,4), b(5,6);
	RectManager man;
	
	man.copy(b, a); // a를 b에 복사한다.
	if(man.equals(a, b)) cout << "equal" << endl;
	else cout << "not equal" << endl;
}

 

또한, 프렌드 선언은 클래스 내에 private, public 영역 등 아무 위치에나 가능하다.

728x90

'Programming Language > C++' 카테고리의 다른 글

[C++] 단항 연산자 중복과 프렌드로 구현하기  (2) 2023.12.06
[C++] 연산자 중복  (0) 2023.12.06
[C++] static 멤버  (0) 2023.12.05
[C++] 함수 중복  (0) 2023.12.04
[C++] 복사 생성자  (1) 2023.12.04