728x90
황기태 저자의 명품 C++ Programming 개정판을 읽고 학습한 내용을 정리한 포스트입니다!
https://search.shopping.naver.com/book/catalog/32436115747
연산자 중복
+기호를 사용하여 숫자 더하기, 문자 더하기 등 다양한 행위를 할 수 있는데, 동일한 연산 혹은 기호(+)를 대상(피연산자)에 따라 서로 다르 의미로 해석하는 일종의 다형성(polymorphism)이다.
- C++에서도 같은 이름의 함수를 여러 개 만들 수 있는 것이 함수 중복(function overloading)이라면, 피연산자에 따라 서로 다른 연산을 하도록 동일한 연산자를 중복해서 작성하는 것이 연산자 중복(operator overloading)
- 간단히 + 연산자를 활용하는 예시를 보자
// 숫자 더하기
int a = 2, b = 3, c;
c = a+b;
// 두 개의 문자열 합치기
string a = "C", c;
c = a + "++" // c = C++
// 두 개의 배열 더하기
SortedArray a(2, 5, 9), b(3, 7, 10), c
c = a+b; // c = {2, 3, 5, 7, 9, 10} 정렬된 두 배열을 결합한 새로운 배열 생성
연산자 중복의 특징
1. C++ 언어에 본래 있는 연산자만 중복 가능
+, -, *, /, ==, !=, %, && 등 본래부터 있는 연산자에 새로운 의미 부여는 가능하지만, %%와 같이 새로운 연산자는 불가
2. 연산자 중복은 피연산자의 타입이 다른 연산을 새로 정의하는 것이다.
- 기본 + 연산자의 피연산자는 모두 숫자
- 따라서, + 연산자를 새로 중복하려면 '객체 + 수', '수 + 객체', '객체 + 객체'와 같이 정수나 실수가 아닌 객체나 값을 더하는 + 연산이어야 한다.
3. 연산자 중복은 함수를 통해 이루어진다.
- 새로운 연산 처리를 수행하는 함수를 구현하는 것
- 이 함수를 연산자 함수(operator function)이라고 한다.
4. 연산자 중복은 반드시 클래스와 관계를 가진다.
- 중복된 연산자는 반드시 피연산자에 객체를 동반한다.
- 그러므로 연산자 함수는 클래스의 멤버 함수로 구현하든지, 아니면 전역 함수로 구현하고 클래스에 프렌드 함수로 선언
5. 연산자 중복으로 피연산자의 개수를 바꿀 수 없다.
- 이항 연산자 +에 대해, 피연산자가 1개 혹은 3개인 + 연산자로 중복할 수 없다.
6. 연산자 중복으로 연산의 우선순위를 바꿀 수 없다.
- '2+5*6'의 경우 *연산자의 우선순위가 +보다 높아 먼저 계산된다.
- 이런 연산의 순위를 바꿀 수 있는 연산자 중복은 불가능하다.
7. 모든 연산자가 중복 가능한 것은 아니다.
연산자 함수 선언과 연산자 함수 개요
연산자 함수는 2가지 방법으로 작성 가능하다.
- 클래스의 멤버 함수로 구현
- 외부 함수로 구현하고 클래스의 프렌드 함수로 선언
리턴타입 operator 연산자(매개변수리스트);
- 연산자 함수 이름이 'operator' 키워드와 '연산자'로 구성된다는 점 외에는 보통의 함수 선언과 동일하다.
- 또한, 외부 함수로 구현하는 것과, 클래스 멤버 함수로 구현하느냐에 따라 매개 변수 리스트는 달라진다.
외부 함수로 구현하고 클래스에 프렌드 함수로 선언하는 경우
Color operator + (Color op1, Color op2); // 외부 전역 함수
bool operator == (Color op1, Color op2); // 외부 전역 함수
...
class Color {
...
friend Color operator + (Color op1, Color op2); // 프렌드 선언
friend bool operator == (Color op1, Color op2); // 프렌드 선언
};
클래스의 멤버 함수로 선언되는 경우
class Color {
...
Color operator + (Color op2); // 왼쪽 피연산자는 객체 자신이고 오른쪽 피연산자가 op2에 전달
bool operator == (Color op2); // 왼쪽 피연산자는 객체 자신이고 오른쪽 피연산자가 op2에 전달
};
- +나 ==의 오른쪽 피연산자만 매개 변수 op2에 전달되고, 왼쪽 피연산자는 객체 자신이므로 매개 변수에 전달되지 않는다.
어떻게 구현되었든 +나 == 연산자는 아래와 같이 사용된다.
Color a(BLUE), b(RED), c;
c = a + b; // Color operator + (Color op2)나 Color operator + (Color op1, Color op2) 중 구현된 것을 호출한다.
if (a == b) { // bool operator == (Color op2)나 bool operator == (Color op1, Color op2) 중 구현된 것을 호출한다.
...
}
이항 연산자 중복
- 피연산자가 2개인 이항 연산자(binary operator)를 중복해보면 전체적으로 연산자 함수를 선언하고 구현하는 방법을 알 수 있을 것이다.
class Power {
int kick;
int punch;
public:
Power(int kick = 0, int punch = 0) {
this->kick = kick;
this->punch = punch;
}
};
산술 연산자를 대표하여 두 개의 Power 객체를 더하는 + 연산자를 선언하고 구현하는 과정을 보자
연산자 착안
- 연산자를 만들기 전에 우선 +의 의미를 결정해야 한다.
- + 연산의 의미를 정하는 것은 전적으로 개발자의 몫이다. 여기서는 kick과 punch를 더하는 것으로 정희한다.
Power a(3, 5), b(4, 6), c;
// + 연산자는 아래와 같이 사용한다.
c = a + b; // 두 개의 파워 개체를 더하는 + 연산
연산자 함수 선언
- c++의 기본 + 연산에서는 피연산자에 수 이외의 값이 올 수 없기 때문에, 컴파일러는 a+b의 연산이 C++의 기본 더하기로 처리될 수 없음을 판단한다.
- 이후, Power 클래스에 Power 객체를 더하는 + 연산자 함수가 새로 선언되어 있는지 찾고 이를 위해 컴파일러는 a+b 식을 아래와 같이 변형한다.
a . = ( b );
- 이 식은 Power 객체 a의 멤버 함수 operator+()를 호출하며, b를 매개 변수로 넘겨주는 함수 호출이다.
- 이 호철이 성공할 수 있도록 operator+() 함수를 클래스 멤버 함수로 선언한다.
class Power {
Power operator+ (Power op2);
};
- operator+() 함수는 리턴 타입을 Power로 하고, 더한 결과로 새로운 Power 객체를 리턴한다.
연산자 함수 구현
Power Power::operator+(Power op2) {
Power tmp;
tmp.kick = this->kick + op2.kick;
tmp.punch = this->punch + op2.punch;
return tmp;
}
- 여기서 this는 Power 객체 a 자신에 대한 포인터
- op2는 Power 객체 b를 전달받은 매개 변수
- 따라서 this->kick + op2.kick;은 a의 kick과 b의 kick을 더하는 것이다.
Tip!!! 연산자 함수의 참조 매개 변수와 리턴 타입
- 참조 매개 변수를 사용하면 매개 변수로 객체가 복사되지 않기에 효과적이나, 원본 객체 수정이 가능하므로 주의해야함
Power operator+ (Power op2);
// 아래와 같다.
Power operator+ (Power &op2);
#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; // 파워 객체 + 연산
a.show();
b.show();
c.show();
}
== 연산자 중복
#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(kick==op2.kick && 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;
}
+= 연산자 중복
- 이 연산자에서 주목할 점은 아래와 같다.
- (a+=b) += b;에서 += 연산자 함수가 객체 a를 리턴한다면 a의 복사본을 리턴한다.
- 그러면 그 다음에 실행되는 +=b는 복사본 a에 연산되므로 원본에는 변함이 없다.
- 따라서 += 연산자의 리턴 타입은 Power&로 하여 객체 a의 참조를 리턴하고, 이는 this를 이용하여 결과를 리턴한다는 점이다.
#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) {
kick = kick + op2.kick; // kick 더하기
punch = punch + op2.punch; // punch 더하기
return *this; // 합한 결과 리턴
}
int main() {
Power a(3,5), b(4,6), c;
a.show();
b.show();
c = a += b; // 파워 객체 더하기
a.show();
c.show();
}
실습해보기 : +연산자 작성 b = a + 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();
Power operator+ (int op2); // + 연산자 함수 선언
};
void Power::show() {
cout << "kick=" << kick << ',' << "punch=" << punch << endl;
}
Power Power::operator+(int op2) {
Power tmp; // 임시 객체 생성
tmp.kick = kick + op2; // kick에 op2 더하기
tmp.punch = punch + op2; // punch에 op2 더하기
return tmp; // 임시 객체 리턴
}
int main() {
Power a(3,5), b;
a.show();
b.show();
b = a + 2; // 파워 객체와 정수 더하기
a.show();
b.show();
}
단항 연산자 중복에 대해선 다음 게시물에서 알아보자..!
728x90
'Programming Language > C++' 카테고리의 다른 글
[C++] 상속 (1) | 2023.12.06 |
---|---|
[C++] 단항 연산자 중복과 프렌드로 구현하기 (2) | 2023.12.06 |
[C++] 프렌드 (1) | 2023.12.05 |
[C++] static 멤버 (0) | 2023.12.05 |
[C++] 함수 중복 (0) | 2023.12.04 |