프로그래밍 언어/C++

9) friend와 연산자 중복

busy맨 2023. 12. 8. 22:37

1. C++에서의 friend

1) friend 함수

  • 클래스의 멤버 함수가 아닌 외부 함수
    • 전역함수, 다른 클래스의 멤버함수
  • friend 키워드로 클래스 내에 선언된 함수 : friend 함수라고 부름
    • 클래스 정의 안쪽에 friend 키워드를 쓰고 함수의 선언을 적어줌
    • 클래스의 모든 멤버를 접근할 수 있는 권한 부여
  • friend 선언의 필요성
    • 클래스의 멤버로 선언하기에는 무리가 있고, 클래스의 모든 멤버를 자유롭게 접근할 수 있는 일부 외부 함수 필요

// 1. 외부함수 equals()를 Rect 클래스에 friend로 선언 
class Rect { // Rect 클래스 선언
...
friend bool equals(Rect r, Rect s);
};

// 2. RectManager 클래스의 equals() 멤버 함수를 Rect 클래스에 friend로 선언
class Rect {
.............
friend bool RectManager::equals(Rect r, Rect s);
};

// 3. RectManager 클래스의 모든 멤버 함수를 Rect 클래스에 friend로 선언
class Rect {
.............
friend RectManager;
};

 

Ex) 전역함수를 friend로 선언

#include <iostream>
using namespace std;

class Rect;
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);	//friend로 선언된 함수는 private 변수에 접근할 수 있다.
};

bool equals(Rect r, Rect s) { // 외부 함수
	if (r.width == s.width && r.height == s.height) return true;
	else return false;
}

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

 

Ex) 다른 클래스의 멤버 함수를 friend로 선언

#include <iostream>
using namespace std;

class Rect;

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

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

bool RectManager::equals(Rect r, Rect s) {
	if (r.width == s.width && r.height == s.height) return true;
	else return false;
}

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

 

Ex) 다른 클래스 전체를 friend로 선언

#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 클래스를 friend로 선언
};

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;
}

 

 

2. 연산자 중복

1) 연산자 중복의 특징

  • 본래부터 있던 연산자에 새로운 의미 정의
  • C++ 본래 존재하는 연산자만 중복 가능
  • 피 연산자 타입이 다른 새로운 연산 정의
  • 연산자는 함수 형태로 구현 → 연산자 함수(operator function)
  • 반드시 클래스와 관계를 가짐
  • 피연산자의 개수를 바꿀 수 없음
  • 연산의 우선 순위 변경 X
  • 모든 연산자가 중복 가능하지 않음
  • 중복 가능한 연산

  • 중복 불가능한 연산자

2) 연산자 함수

  • 구현 방법
    1. 클래스의 멤버 함수로 구현
    2. 외부 함수로 구현하고 클래스에 friend 함수로 선언
  • 형식

 

Ex) 멤버함수로 이항 연산자 중복 구현1: + 연산자 중복

#include <iostream>
using namespace std;

class Power {
	int kick;
	int punch;
public:
	Power(int kick = 0, int punch = 0) {
		this->kick = kick; this->punch = punch;
	}
	void show();
	Power operator+(Power op2); // + 연산자 함수 선언
};

void Power::show() {
	cout << "kick=" << kick << ',' << "punch=" << punch << endl;
}

Power Power::operator+(Power op2) {	// +연산자 멤버 함수 구현
	Power tmp; // 임시 객체 생성
	tmp.kick = this->kick + op2.kick; // kick 더하기
	tmp.punch = this->punch + op2.punch; // punch 더하기
	return tmp; // 더한 결과 리턴
}

int main() 
{
	Power a(3, 5), b(4, 6), c;
	c = a + b; // Power 객체 + 연산
	a.show();
	b.show();
	c.show();
}

 

Ex) 멤버 함수로 이항 연산자 중복 구현2: ==연산자 중복

#include <iostream>
using namespace std;

class Power {
	int kick;
	int punch;
public:
	Power(int kick = 0, int punch = 0) {
		this->kick = kick; this->punch = punch;
	}
	void show();
	bool operator==(Power op2); // + 연산자 함수 선언
};

void Power::show() {
	cout << "kick=" << kick << ',' << "punch=" << punch << endl;
}

bool Power::operator==(Power op2) {
	if (this->kick == op2.kick && this->punch == op2.punch)
		return true;
	else return false;
}

int main() 
{
	Power a(3, 5), b(3, 5); // 2 개의 동일한 파워 객체 생성
	a.show();
	b.show();
	if (a == b) cout << "두 파워가 같다." << endl;
	else cout << "두 파워가 같지 않다." << endl;
}

 

3) 멤버 함수로 단항 연산자 중복 구현

  • 단항 연산자
    • 피연산자가 하나 뿐인 연산자
      • 연산자 중복 방식은 이항 연산자의 경우와 거의 유사함
    • 단항 연산자 종류
      • 전위 연산자(prefix operator)
        • !op, ~op, ++op, --op
      • 후위 연산자(postfix operator)
        • op++, op--

 

Ex) 멤버 함수로 단항 연산자 중복 구현1 : 전위 ++ 연산자 중복

#include <iostream>
using namespace std;

class Power {
	int kick;
	int punch;
public:
	Power(int kick = 0, int punch = 0) {
		this->kick = kick; this->punch = punch;
	}
	void show();
	Power operator++ (); // 전위 ++ 연산자 함수 선언
};

void Power::show() {
	cout << "kick=" << kick << ',' << "punch=" << punch << endl;
}
Power Power::operator++() {
	kick++;
	punch++;
	return *this; // 변경된 객체 자신(객체 a) 리턴
}

int main()
{
	Power a(3, 5), b;
	a.show();
	b.show();
	b = ++a; // 전위 ++ 연산자 사용
	++a;
	a.show();
	b.show();
}

 

Ex) 2+a 덧셈을 위한 + 연산자 함수 작성

#include <iostream>
using namespace std;
class Power {
	int kick;
	int punch;
public:
	Power(int kick = 0, int punch = 0) {
		this->kick = kick; this->punch = punch;
	}
	void show();
	friend Power operator+(int op1, Power op2); // 프렌드 선언
};
void Power::show() {
	cout << "kick=" << kick << ',' << "punch=" << punch << endl;
}
Power operator+(int op1, Power op2) {
	Power tmp; // 임시 객체 생성
	tmp.kick = op1 + op2.kick; // kick 더하기
	tmp.punch = op1 + op2.punch; // punch 더하기
	return tmp; // 임시 객체 리턴
}
int main()
{
	Power a(3, 5), b;
	a.show();
	b.show();
	b = 2 + a; // 파워 객체 더하기 연산
	a.show();
	b.show();
}

 

Ex) a+b를 위한 연산자 함수를 friend로 작성

#include <iostream>
using namespace std;
class Power {
	int kick;
	int punch;
public:
	Power(int kick = 0, int punch = 0) {
		this->kick = kick; this->punch = punch;
	}
	void show();
	friend Power operator+(Power op1, Power op2); // 프렌드 선언
};
void Power::show() {
	cout << "kick=" << kick << ',' << "punch=" << punch << endl;
}
Power operator+(Power op1, Power op2) {
	Power tmp; // 임시 객체 생성
	tmp.kick = op1.kick + op2.kick; // kick 더하기
	tmp.punch = op1.punch + op2.punch; // punch 더하기
	return tmp; // 임시 객체 리턴
}
int main() 
{
	Power a(3, 5), b(4, 6), c;
	c = a + b; // 파워 객체 + 연산
	a.show();
	b.show();
	c.show();
}

'프로그래밍 언어 > C++' 카테고리의 다른 글

11) 가상 함수와 추상 클래스  (0) 2023.12.09
10) 상속  (0) 2023.12.09
8) 함수와 참조, 복사생성자  (0) 2023.12.08
7) 여러가지 객체의 생성 방법  (1) 2023.11.03
6) 접근 지정자, static 멤버  (0) 2023.11.02