[연산자 오버로딩] 연산자 오버로딩과 반환 값
연산자 오버로딩을 진행하다 보면, 반환 값에 대해 고민하는 순간들이 있었습니다.
이에 헷갈리고, 기억이 애매할 때 돌아보기 위해 메모를 작성합니다.
연산자 오버로딩
연산자 오버로딩은 C++에서 제공하는 기본 타입이 아닌 클래스 타입, 즉 사용자 정의 타입에도
연산자를 사용할 수 있게 하는 문법입니다.
- 뇌를 자극하는 C++ STL -
1. 멤버 함수로 연산자 오버로딩
클래스의 멤버 함수로 연산자를 오버로딩 할 경우에는 해당 클래스의 객체를 통해 호출합니다.
샘플 클래스를 예시로 설명하고 반환 값에 대한 정보를 정리하겠습니다.
class Sample
{
private:
int value;
public:
Sample(int n) : value(n) { }
};
1-1 단항 연산자
단항 연산자는 하나의 피연산자를 가지는 연산자이며, 클래스 멤버 함수로 단항 연산자를 오버로딩 할 경우에는
매개변수는 필요하지 않습니다.
Sample& operator++() // 전위 증가, 참조를 반환합니다
{
++value;
return *this;
}
Sample operator++(int) // 후위 증가, int를 매개 변수에 전달한 것은 문법적 규칙
{
Sample Temp(this->value);
++value;
return Temp;
}
전위 증가 연산자의 경우 참조를 반환해야 합니다.
연산을 수행한 후 반환되는 값은 연산이 적용된 자신이어야 합니다.
연산의 결과를 호출한 객체에 즉시 반영되어야 합니다.
또한 후위 증가의 매개 변수에 int를 작성한 것은
전위 증가 연산자와 후위 증가 연산자를 구별하기 위한 문법적 규칙입니다.
사용은 이렇게 할 수 있습니다.
Sample test(3);
std::cout << (++test).display() << std::endl ; // 4 반환
int temp = test++.display(); // 4 반환, 실제 값은 5
1-2 이항 연산자
이항 연산자의 반환 값은 사칙 연산의 경우 참조가 아닌 값을 반환합니다.
또한 매개변수로 다른 객체를 참조 받아 연산을 진행합니다.
Sample operator+(const Sample& other)
{
return Sample(this->value + other.value);
}
눈여겨 볼 부분은 참조가 아닌 값 형태로 반환을 하고 있습니다.
이런 문장이 있을 때, 만약 참조의 형태로 반환하면 어떤 일이 일어날까요?
Sample a = b + c + b;
우선 컴파일러는 위 문장을 이렇게 해석합니다.
Sample a = b.operator+(c).operator+(b);
이를 풀어서 해석하면
Sample& temp1 = b.operator+(c); // 첫 번째 덧셈 결과 (b 자신을 참조)
Sample& temp2 = temp1.operator+(b); // 두 번째 덧셈 결과 (b 자신을 참조)
Sample a = temp2; // 최종 결과를 a에 할당
b에 이미 c가 더해진 값을, temp2 에서 다시 원본 B인 줄 알고 더하고 있습니다.
이 때문에 사칙 연산은 모두 값 형태로 반환합니다.
1-3 대입 연산자
대입과 관련된 모든 연산은 참조를 반환해야 합니다.
a = b = c;
이러한 구조로 설명을 많이 하였다.
값을 반환한다면 자기 자신이 아닌 복사본이 그 자리에 위치하게 된다.
잘 설명한 글이 있어 예제를 가져오게 되었다.
아래와 같은 코드가 있다고 가정해보자.
class Sample
{
private:
int x;
int y;
public:
Sample(int a, int b) : x(a), y(b) { }
Sample& operator=(const Sample& other)
{
x = other.x;
y = other.y;
return *this;
}
};
int main()
{
Sample a(1, 2);
Sample b(3, 4);
Sample c(5, 6);
a = b = c;
}
대입 연산은 우측 연관 연산이다.
즉 ,위의 경우 a = (b = c);
1. AAA operator=(const AAA& rhs);
2. AAA& operator=(const AAA& rhs);
그럼 참조자를 반환하지 않으면 어떻게 될까?
1번의 경우 반환되는 값이 복사생성자에 의해 복사되어 리턴된다.
그리고 자기자신이 아닌 복사본이 그 자리에 위치하게 되는 것.
단항연산자를 오버로딩 하는 경우, 참조자를 리턴받지 않으면
++(++a); 이와같은 연산이 불가능하다.
밑줄 친 부분에 자기자신이 아닌, 복사본이 위치하기 때문에
제대로된 연산이 이루어 지지 않는다.
단항 연산자 항목에서 전위 연산자는 참조를 반환한다고 하였다.
이와 같은 이유 때문에 대입 연산자는 참조를 반환한다.
1-4 멤버 함수의 형태로만 오버로딩 가능한 연산자
- =
- ()
- []
- ->
'개념과 활용 > C++' 카테고리의 다른 글
[C++] new [], delete [] (0) | 2024.06.18 |
---|---|
[상속] 접근 지정자와 상속 접근 지정자 (0) | 2024.06.13 |
[복사 생략] 이동 생성자와 이동 대입 연산자 (0) | 2024.06.11 |
[복사 생략] 복사 생략 (0) | 2024.06.11 |
[다형성] 추상 클래스와 가상 함수 테이블 (0) | 2024.06.08 |
댓글