[ 10주차 - 2 ]
연산자 중복
연산자 중복 사용 이유 : 연산자의 의미를 특정한 클래스를 위해 정의하는 것을 허용
type classname::operator#(arg_list){
operation relative to the class
}
# : 중복 사용할 연산자
type : 명시된 연산에 의해 반환되는 값의 형
연산자 중복이 필요한 이유 : 정수, 실수 덧셈을 위해 사용하는 + 연산자를 객체끼리의 덧셈에 적용하고 싶은 경우,
클래스에 +에 대한 연산자 중복을 정의해야한다. 해당 클래스 객체끼리 연산을 수행하고 싶은 경우, 해당 연산자에
대해 중복을 명시해놓으면 객체끼리 연산을 할 수 있게 된다. = 같은 치환 연산자는 같은 클래스의 객체들끼리는
치환이 허용된다. =은 명시가 되어있지만 다른 치환연산자를 사용하고 싶을 경우에는 명시를 해줘야한다.
멤버 함수를 사용하는 연산자 중복
#include <iostream>
using namespace std;
class three_d {
private:
int x, y, z;
public:
three_d() {
x = y = z = 0;
}
three_d(int i, int j, int k) {
x = i;
y = j;
z = k;
}
three_d operator+(three_d op2);//op1을 포함하고 있다.
three_d operator=(three_d op2);//op1을 포함하고 있다.
void show();
};
int main() {
three_d a(1, 2, 3), b(10, 10, 10), c;
a.show();
b.show();
c = a + b; // a와 b를 더한다.
c.show();
c = a + b + c; // a,b,c를 더한다.
c.show();
c = b = a; // 다중 치환을 보여준다.
c.show();
b.show();
return 0;
}
+와 = 연산자에 대해 중복을 한다. +가 연산의 결과로 리턴하는 자료형은 three_d이다.
+나 = 같은 치환 연산자는 2개의 피연산자를 가지고 있다. 첫번째 피연산자는 +가 포함되어 있는 int형 변수들이고,
두번째 피연산자는 매개변수로 들어오는 op2이다.
클래스 객체에 대한 덧셈을 수행할 때는 연산자 중복으로 선언한 연산자가 호출이 된다. operator+는 일종의 멤버함수
이지만 기호와 연결을 시켜서 메인함수에서 +기호가 사용이 될 때는 실제로는 op2를 호출한다.
즉, three_d 클래스 객체인 a와 b를 더할 때는 a와 b가 가지고 있는 operator+ 함수가 호출이 된다.
그리고 객체 a에는 피연산자가 2개가 존재하게 된다. a가 가지고 있는 정수형 변수에 대한 피연산자와 operator+의 매개변수로 들어오는 three_d 객체에 대한 피연산자이다. 치환 연산자의 경우도 마찬가지이다.
three_d three_d::operator+(three_d op2) {
three_d temp;
temp.x = x + op2.x;
temp.y = y + op2.y;
temp.z = z + op2.z;
return temp;
}
three_d three_d::operator=(three_d op2) {
x = op2.x;
y = op2.y;
x = op2.z;
return *this;
}
객체 a와 b에는 x,y,z,가 들어있다. temp 라는 three_d의 임시객체를 생성해서 a와 b가 가지고 있는 각각의 변수를 operator+를 통해 더해서 temp의 x,y,z, 변수에 넣어주고 temp 객체의 결과를 리턴하게 된다.
치환 연산자의 경우 a = b;의 경우 a의 x,y,z에다가 operator=을 통해 b가 가지고 있는 값을 넣어줄 수 있다.
즉, 객체에 대한 +와 =를 수행할 경우 operator+와 operato=가 수행이 된다.
멤버 함수가 이항 연산자를 중복하기 위해 사용할 때, 연산자의 왼쪽에 있는 객체가 연산자 함수를 호출하며, this를 통해 묵시적으로 함수에 전달된다. 오른쪽의 객체는 연산자의 함수에게 매개변수로서 전달된다.
#include <iostream>
using namespace std;
class three_d {
private:
int x, y, z;
public:
three_d() {
x = y = z = 0;
}
three_d(int i, int j, int k) {
x = i;
y = j;
z = k;
}
three_d operator+(three_d op2);//op1을 포함하고 있다.
three_d operator=(three_d op2);//op1을 포함하고 있다.
void show();
};
three_d three_d::operator+(three_d op2) {
three_d temp;
temp.x = x + op2.x;
temp.y = y + op2.y;
temp.z = z + op2.z;
return temp;
}
three_d three_d::operator=(three_d op2) {
x = op2.x;
y = op2.y;
x = op2.z;
return *this;
}
void three_d::show() {
cout << x << ", ";
cout << y << ", ";
cout << z << "\n";
}
int main() {
three_d a(1, 2, 3), b(10, 10, 10), c;
a.show();
b.show();
c = a + b; // a와 b를 더한다.
c.show();
c = a + b + c; // a,b,c를 더한다.
c.show();
c = b = a; // 다중 치환을 보여준다.
c.show();
b.show();
return 0;
}
연산자 중복을 사용해서 + 기호를 클래스 객체에다가 적용할 수 있다.
단항 연산자를 중복하기
int main() {
three_d a(1, 2, 3), b(10, 10, 10), c;
c = a + b; // a와 b를 더한다.
++c; // 접두사 증가
c++; // 접미사 증가
a = ++c; // a는 증가 후에 c의 값을 받는다.
a = c++; // a는 증가에 앞서 c의 값을 받는다.
return 0;
}
++c나 c++의 결과는 거의 다르지 않지만 그 값을 치환을 해서 객체에 저장해 줄 경우에는 객체에 저장되는 값이 완전히 달라진다.
접두사 버전에서 ++는 단항연산자이기 때문에 피연산자가 하나만 존재한다. 그러므로 피연산자는 클래스 객체에 해당하는 변수( x,y,z )에 해당한다. 피연산자가 하나밖에 없기 때문에 매개변수는 없다.
접미사 버전에서는 매개변수를 명시한다. 실제로 매개변수에 전달되는 인자는 없지만 접두사와 접미사를 구분하기 위해서 사용하게 된다.
three_d three_d::operator++() { // 접두사
x++;
y++;
z++;
return *this; // 변경된 값을 리턴
}
three_d three_d::operator++(int notused) { // 접미사
three_d temp = *this; // temp 라는 임시 변수에 c의 값을 저장하고 증가
x++;
y++;
z++;
return temp; // 원래의 값을 리턴
}
#include <iostream>
using namespace std;
class three_d {
private:
int x, y, z;
public:
three_d() {
x = y = z = 0;
}
three_d(int i, int j, int k) {
x = i;
y = j;
z = k;
}
three_d operator+(three_d op2);//op1을 포함하고 있다.
three_d operator=(three_d op2);//op1을 포함하고 있다.
three_d operator++(); // ++의 접두사 버전 ( ++c )
three_d operator++(int notused); // ++의 접미사 버전 ( c++ )
void show();
};
three_d three_d::operator+(three_d op2) {
three_d temp;
temp.x = x + op2.x;
temp.y = y + op2.y;
temp.z = z + op2.z;
return temp;
}
three_d three_d::operator=(three_d op2) {
x = op2.x;
y = op2.y;
x = op2.z;
return *this;
}
three_d three_d::operator++() { // 접두사
x++;
y++;
z++;
return *this;
}
three_d three_d::operator++(int notused) { // 접미사
three_d temp = *this; // temp 라는 임시 변수에 c의 값을 저장
x++;
y++;
z++;
return temp;
}
void three_d::show() {
cout << x << ", ";
cout << y << ", ";
cout << z << "\n";
}
int main() {
three_d a(1, 2, 3), b(10, 10, 10), c;
a.show();
b.show();
c = a + b; // a와 b를 더한다.
c.show();
c = a + b + c; // a,b,c를 더한다.
c.show();
c = b = a; // 다중 치환을 보여준다.
c.show();
b.show();
++c; // 접두사 증가
c.show();
c++; // 접미사 증가
c.show();
a = ++c; // a는 증가 후에 c의 값을 받는다.
a.show();
c.show();
a = c++; // a는 증가에 앞서 c의 값을 받는다.
a.show();
c.show();
return 0;
}
연산자 중복에 대한 힌트와 제약
중복된 연산자에게 전혀 새로운 의미를 줄 수 있지만 그것의 새로운 의미가 원래의 의미와 연관될 때가 가장 좋다.
연산자 중복의 제약
- 연산자의 우선 순위를 변경할 수 없다.
- 연산자 함수가 피연산자를 무시할 수 있지만, 연산자에 의해 요구되는 피연산자의 수를 변경할 수 없다.
- 연산자 함수는 디폴트 인수를 가질 수 없다.
중복할 수 없는 연산자 4가지 : . , :: , *, ?
실습 문제
three_d 클래스에서 연산자를 중복해보고 메인함수에서 실행하기
1. * ( 곱하기 )
2. -- ( 접두사 )
3. -- ( 접미사 )
'2CHAECHAE 학교생활 > 객체지향프로그래밍(C++)' 카테고리의 다른 글
[ 객체지향프로그래밍(C++) 12주차 ① ] (0) | 2022.05.22 |
---|---|
[ 객체지향프로그래밍(C++) 11주차 ① ] (0) | 2022.05.16 |
[ 객체지향프로그래밍(C++) 10주차 ① ] (0) | 2022.05.09 |
[ 객체지향프로그래밍(C++) 9주차 ② ] (0) | 2022.05.01 |
[ 객체지향프로그래밍(C++) 9주차 ① ] (0) | 2022.05.01 |