chapter 7 프렌드와 연산자 중복

박준우·2025년 3월 15일

명품C++프로그래밍

목록 보기
7/10

1.프랜드의 개념

프랜드란? 클래스 외부 함수(다른 클래스, 전역함수 등)임에도, private나, protect를 접근해야하는 특별한 경우에 이를 프랜드함수로 지정해 이를 접근할 수 있다.

전역함수 freind로 만들기.

include <iostream>
using namespace std;

class Rect; // 후방참조를 막기 위한 Rect클래스 선언
bool equals(Rect r, Rect s); //전역 함수를 선언 

class 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가,
    															//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;
}
    

참고로 전방참조, 후방참조는 자기위치 기준 앞의 코드를 읽는가, 뒤의 코드를 읽는가로 구분되며, 후방참조는 불가능하기에, 에러를 방지하기 위해 위와 같은 Rect클래스를 선언한것이다.

다른 클래스의 맴버함수를 프랜드로 만들기.

include <iostream>
using namespace std;

class Rect; // 후방참조를 막기 위한 Rect클래스 선언
class RectManager{
	public:
    	bool equals(Rect r, Rect s); 
};

class 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맴버함수를 프랜드 선언
										//만약 RectManager전체를 friend하고 싶으면 함수없이
                                        //friend RectManager 하면됨.
};

bool equals(Rect r, Rect s){
	if(r.width == s.width && r.height == s.height) return true; //프랜드인 width과 height를 접근가능
    else return false;
}
    
int main (){
	Rect a(3,4), b(4,5);
    RectManager man;
    
    if(man.equals(a,b)) cout << "equal" << endl;
    else cout << "not equal" << endl;
}
    

2. 연산자 중복(연산자 오버로딩)

연산자 중복이란? +, - , *, / >>, <<, 와 같이, 본래있던 계산 기능에 추가기능을 넣을 수 있는 기능이다. 보통 객체간의 연산을 지원하기 위해 사용한다.

사용방법

  1. 외부 함수로 구현하고 클래스에 프랜드 함수로 선언하는 경우
Color operator + (Color op1, Color op2)

class Color P
	friend Color operator + (Color op1, Color op2);
  1. 클래스의 맴버 함수로 선언하는 경우
Color operator + (Color op1)

class Color{
	Color operator + (Color op1);

지금부터는 구체적 사용예를 살펴보겠다.

3. 이항 연산자 중복

+라는 연산자에 객체끼리의 덧샘을 표기하기.

class Power{
	int kick;
    int punch;
public:
	Power(int Kick=0, int punch=0){
    	this-> kick = kick;
        this->punch = punch;
        }
 };
 

위와 같은 코드에서 아래와 같이 3개의 객체를 생성하고 a와 b를 더했다.

Power a(3,5), b(4,6), c;
c = a+b;

그러면 a와 b를 덧샘할 수 없음을 깨닫고, 아래와 같이 식을 변환한다.

c = a.+(b);// a의 맴버함수 operatror+()를 호출하여, b를 매개 변수로 넘겨주는 함수의 호출이다.
그후 새로운 power type의 객체 c를 출력한다. 

class Power{
	int kick;
    int punch;
Public:
	Power operator+ (Power op1); // operator+(.+), op1(b) 
   
};

실제 코드화(+, ==, +=)

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); //+ 중복연산자 함수를 선언
    bool operator==(Power op2); //== 중복연산자 함수를 선언
	Power& operator+=(Power op2); //+= 중복연산자 함수를 선언
 	// 이때 a에는 복사값이 아닌 실제값을 가져오기위해 참조에 의한 복사 연산을 사용한다.
 };
 
 void Power::show(){
 	cout << "kick=" << kick << "punch=" << punch << endl;
	};


Power Power::operator+(Power op2){ // +중복연산자 함수 구현
	Power tmp;
    tmp.kick = this->kick + op2.kick; //this->kick은 a의 kick이다. 
    tmp.punch = this->punch + op2.punch;
    return tmp;
};

Power Power::operator==(Power op2){ // ==중복연산자 함수 구현
	if(kick==op2.kick && punch==op2.punch) return true;
    else return false;
};

Power &Power::operator+=(Power op2){ // +=중복연산자 함수 구현 + 참조에 의한 복사
	kick = kick + op2.kick;
    punch = punch + op2.punch;
    return *this; //return *this란? 
};

int main(){ 
    Power a(3,5), b(4,6), c;
	
    c = a+b; // c객체 생성후 더하기
    a.show();
    b.show();
    c.show();
    
    if(a == b) cout << "두 데미자가 같다." << endl;
    else cout << "두 데미지가 같지 않다. << endl;
    
    c= a+= b;
    a.show();
    b.show();
 };

단항 연산자 중복

단항연산자란? 피연산자가 1개인 것으로 연산자의 위치에 따라 전위와 후위로 나뉜다.

전위: !op, ~op, ++op, --op
후위: op++, op--

전위와 후위에 따라, 구현부가 달라짐으로, 구현에 주의해야한다.

전위 연산자 구현

class Power{
	int kick;
    int punch;
public:
	Power(int Kick=0, int punch=0){
    	this-> kick = kick;
        this->punch = punch;
        }
    void show();
    Power &operator++(); //++ 전위중복연산자 함수를 선언 + 실제값 변경 &사용
    bool operator!();
};

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

Power &Power::operator++(){ // ++전위 중복연산자 함수 구현
	kick++;
    punch++;
    return *this;			//실제값 변경위해, &사용 + this 반환
};    

bool Power::operator!(){
	if(kick ==0 && pusch ==0) return true;
    else return false

int main(){ 
    Power a(3,5), b;    
    b = ++a;
    a.show();
    b.show();
    
    if(!a) cout << a의 데미지가 0이다. << endl;
    	else cout << a의 데미지가 0이 아니다. << endl;
    if(!b) cout << b의 파워가 0이다 << endl; 
    	else cout << a의 데미지가 0이 아니다. << endl;
    }

후위 연산자 구현

후위연산자는 전위와 다르게 의미없는 매개변수 1개가 필요하다.
또한, 계산후에 값을 바꾸기 때문에 직접 주소를 받을 필요가 없다.

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

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

Power Power::operator++(intx){ // ++후위 중복연산자 함수 구현
	Power tmp = *this; // 증가이전 값을 tmp에저장 
    punch++;
    return *this;
    return tmp; // tmp를 리턴한다.
};    

외부함수로 연산자 중복 구현하기

외부함수로 중복연산자를 구현하려면 프랜드로 지정해야한다.
그냥 public선언하면 안되나 싶지만, 이는 캡슐화와 맞지 않는 코드 작성법이다.

또한 클래스 내부에서 구현과 다르게, 모든 객체를 매개변수로 받아와야 한다.

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 Power::operator+(Power op1, Power op2){ // +중복연산자 함수 구현
	Power tmp;
    tmp.kick = op1.kick + op2.kick;
    tmp.punch = op1.punch + op2.punch;
	return tmp;
};    

int main(){
	Power a(3,5) b=(4,6) c;
    c= a+b;
    a.show();
    b.show();
    c.show();

6.참조리턴

참조리턴이란? 자기자신의 주소를 리턴하는 것을 의미한다.

class Power{
	int kick;
    int punch;
public:
	Power(int Kick=0, int punch=0){
    	this-> kick = kick;
        this->punch = punch;
        }
    void show();
	Power operator << (int n);
};

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

Power Power::&operator << (int n){ // << 중복연산자 함수 구현
	kick += n;
    punch += n;
    return *this; //자기자신 리턴하기.
};    

int main(){
	Power a(1,2);
    a << 3 << 5 <<6; //3과 5와 6을 순서대로 중복연산자로 자기자신을 리턴하여 더한다.
    a.show()
profile
DB가 좋아요

0개의 댓글