연산자오버로딩
[참고] https://modoocode.com/202
::(범위지정), .(멤버지정), .*(멤버 포인터로 멤버지정)은 연산자 오버로딩 불가
아래는 모두 가능.
+, -, * 와 같은 산술 연산자
+=, -= 와 같은 축약형 연산자
”>=”, “==” 와 같은 비교 연산자
| &&, | 와 같은 논리 연산자 |
-> 나 * 와 같은 멤버 선택 연산자 (여기서 * 는 역참조 연산자 입니다. 포인터에서 *p 할 때 처럼)
++, – 증감 연산자
[] (배열 연산자) 와 심지어 () 까지 (함수 호출 연산자)
까지 모두 여러분이 직접 만들 수 있습니다.
연산자 오버로딩을 사용하기 위해서는, 다음과 같이 오버로딩을 원하는 연산자 함수를 제작하면 됩니다.
(리턴 타입) operator(연산자) (연산자가 받는 인자)
사용예
bool operator==(MyString& str);
사칙 연산에 operator 연산자 오버로딩을 사용하는 예
Complex Complex::operator+(const Complex& c) const {
Complex temp(real + c.real, img + c.img);
return temp;
}
Complex Complex::operator-(const Complex& c) const {
Complex temp(real - c.real, img - c.img);
return temp;
}
Complex Complex::operator*(const Complex& c) const {
Complex temp(real * c.real - img * c.img, real * c.img + img * c.real);
return temp;
}
Complex Complex::operator/(const Complex& c) const {
Complex temp(
(real * c.real + img * c.img) / (c.real * c.real + c.img * c.img),
(img * c.real - real * c.img) / (c.real * c.real + c.img * c.img));
return temp;
}
int main() {
Complex a(1.0, 2.0);
Complex b(3.0, -2.0);
Complex c = a * b;
c.println();
}
위 4 개의 연산자 함수 모두 Complex& 가 아닌 Complex 를 리턴하고 있습니다. 간혹가다,
Complex& operator+(const Complex& c) {
real += c.real;
img += c.img;
return *this;
}
로 잘못 생각하는 경우도 있습니다. 물론 이렇게 설계하였을 경우, Complex 를 리턴하는 연산자 함수는 값의 복사가 일어나기 때문에 속도 저하가 발생하지만 위 처럼 레퍼런스를 리턴하게 되면 값의 복사 대신 레퍼런스만 복사하는 것이므로 큰 속도의 저하는 나타나지 않습니다. 하지만, 위와 같이 operator+ 를 정의할 경우 다음과 같은 문장이 어떻게 처리되는지 생각해봅시다.
Complex a = b + c + b;
아마도 위 문장을 쓴 사람 입장에서는 결과적으로 a = 2 * b + c; 를 의도하였을 것입니다.
하지만, 실제로 처리되는 것을 보자면, (b.plus(c)).plus(b) 가 되는데, b.plus(c) 를 하면서 b 에는 (b + c) 가 들어가고, 거기에 다시 plus(b) 를 하게 된다면 값 자체만 보자면 (b + c) + (b + c) 가 되서 (왜냐하면 현재 b 에는 b + c 가 들어가 있으니까) a = 2 * b + 2 * c 가 되기 때문입니다. 이러한 문제를 막기 위해서는 반드시 사칙 연산의 경우 반드시 값을 리턴해야 만 합니다.
또한 함수 내부에서 읽기만 수행되고 값이 바뀌지 않는 인자들에 대해서는 const 키워드를 붙여주는 것이 바람직합니다. operator+ 의 경우, c 의 값을 읽기만 하지 c 의 값에 어떠한 변화도 주지 않으므로 const Complex& 타입으로 인자를 받았습니다.
대입 연산자 함수
Complex& operator=(const Complex& c);
기본적으로 대입 연산자 함수는, 기존의 사칙연산 연산자 함수르게, 자기 자신을 가리키는 레퍼런스 (Complex&) 을 리턴합니다. 왜 굳이 대입 연산자가 자기 자신을 리턴해야 되냐면,
a = b = c;
위와 같은 코드에서 b = c; 가 b 를 리턴해야지, a = b; 가 성공적으로 수행될 수 있기 때문이죠.
이 때 Complex 타입을 리턴하지 않고 굳이 Complex& 타입을 리턴하냐면, 대입 연산 이후에 불필요한 복사를 방지하기 위해서 입니다.
이와 같은 사실을 바탕으로 operator= 함수를 완성시켜 보면 아래와 같습니다.
Complex& Complex::operator=(const Complex& c)
{
real = c.real;
img = c.img;
return *this;
}
