최근 c++에서 연산자를 매개변수에 따라서 오버로딩(operator overloading)을 할 수 있다는 것을 배웠다.
#include <iostream>
class Vector2D {
int x, y;
public:
Vector2D(int x, int y) : x(x), y(y) {}
int get_x(){
return x;
}
int get_y(){
return y;
}
};
Vector2D operator+(Vector2D& a, Vector2D& b){
int x1 =0, x2 =0;
Vector2D result(x1,x2); // 여기서 내가 새로 만든 객체는 0,0만 할당된다. 실수 1
x1 = a.get_x() + b.get_x();
x2 = a.get_y() + b.get_y();
return result;
}
std::ostream& operator<<(std::ostream& os, Vector2D& a){
os << a.get_x() << ',' << a.get_y();
return os;
}
int main() {
Vector2D v1(10, 2), v2(20, 5);
std::cout << v1+v2 << std::endl; // 이 부분에서 오류가 발생한다. 실수 2
}
x와 y를 멤버로 두는 Vector2D라는 이름의 클래스의 객체를 더하고 출력하는 코드이다.
더하기 연산자 + 는 내가 임의로 만든 클래스의 객체 끼리 더하는 것은 정의되어 있지 않기 때문에
연산자 오버로딩을 통해서 새롭게 정의를 해주어야 한다.
그리고 결과를 출력하는 것도 어떤 방식으로 출력해줘야 하는 지 내가 새로 정의해 주어야 한다.
더하기의 경우
x1 = a.get_x() + b.get_x();
x2 = a.get_y() + b.get_y();
각 객체의 멤버 x와 멤버 y를 더해주는 연산자로 하려했고
cout을 위한 "<<" 연산자의 경우 (내 스크린에 찍어주는 동작)
os << a.get_x() << ',' << a.get_y();
return os;
그 객체의 x와 y좌표를 순서대로 찍어주도록 설정했다.
그런데 문제가 발생하는데..
1. std::cout << v1+v2
실수2라고 적은 부분에서 코드가 제대로 동작하지 않았다.
Invalid operands to binary expression ('std::__1::ostream' (aka 'basic_ostream<char>') and 'Vector2D') // 발생한 오류
피연산자가 잘못됬다는 오류인데 나는 분명히 << 을 (std::ostream& os, Vector2D& a) 해뒀는데
왜 오류가 나는 지 어제 저녁 부터 오늘 아침까지 계속 고민했었다.
구글링도 실력이라는 말이 맞는 게 저 오류를 어떻게 검색해야 할 지도 모르겠어서 혼자 책보면서 고생함..
해결하는 과정에서 2번째 오류를 찾았는데
객체 v3를 새로 만들고 그 v3에 v1+v2 를 대입하면 정상적으로 출력된다.
그런데 v3는 0,0 을 출력한다. 그 이유는
Vector2D operator+(Vector2D& a, Vector2D& b){
int x1 =0, x2 =0;
Vector2D result(x1,x2); // 여기서 내가 새로 만든 객체는 0,0만 할당된다. 실수 1
x1 = a.get_x() + b.get_x();
x2 = a.get_y() + b.get_y();
return result;
}
x1 , x2를 0으로 초기화 한 후 v3객체를 만들고 x1, x2를 바꿔주었기 때문이다.
해결방법으로는 두가지가 있는데
첫째
result.x1 = a.get_x() + b.get_x();
result.x2 = a.get_y() + b.get_y();
로 수정해서 result의 멤버를 바꿔주는 것이다.
둘째
x1 = a.get_x() + b.get_x();
x2 = a.get_y() + b.get_y();
Vector2D result(x1,x2); // 여기서 내가 새로 만든 객체는 0,0만 할당된다. 실수 1
로 순서를 바꿔주는 방법도 있다.
이렇게 해결하고 나니 v3는 잘 인식하는 걸로 보아 << 연산자 오버로딩도 문제없이 잘 작성된 것을 알 수 있었다.
그럼 +연산자 오버로딩에서 문제가 발생한건데
!!핵심!!
함수의 지역변수는 함수가 종료되면 메모리 상에서 사라진다!!!!
라는 점을 간과하고 있었다.
즉 result라는 이름을 가진 객체는 반환되고 나면 메모리상에서 사라지는 것이고
cout<<v1+v2 에서 메모리상에서 사라진 존재를 출력하라고 했기 때문에 오류가 발생한 것이다.
그래서
#include <iostream>
class Vector2D {
int x, y;
public:
Vector2D(int x, int y) : x(x), y(y) {}
int get_x(){
return x;
}
int get_y(){
return y;
}
};
Vector2D& operator+(Vector2D& a, Vector2D& b){
int x1 =0, x2 =0;
x1 = a.get_x() + b.get_x();
x2 = a.get_y() + b.get_y();
Vector2D static result(x1,x2);
return result; //최종 수정
}
std::ostream& operator<<(std::ostream& os, Vector2D& a){
os << a.get_x() << ',' << a.get_y();
return os;
}
int main() {
Vector2D v1(10, 2), v2(20, 5);
std::cout << v1+v2 << std::endl; // 30, 7 출력
}
Vector2D static result(x1,x2); 로 static 선언을 해주어서 함수가 끝나도 메모리상에 남아있도록 해주면
문제없이 30과 7이 출력이 되는 것을 확인할 수있었다.