문제
두 정수 x, y 로 구성된 구조체 Data 가 있다고 하자.
그리고 두 Data 구조체 변수 a, b 를 선언한다.
struct Data{
int x, y;
};
Data a, b;여기서 아래 세 코드 모두 컴파일 에러가 난다. 왜일까?
if(a < b) { ... } // 컴파일 에러
if(a == b) { ... } // 컴파일 에러
Data c = a + b; // 컴파일 에러컴퓨터 입장에서는, 두 구조체 변수가 같을 조건이 무엇인지(==), 크기 비교 조건이 무엇인지(<), 어떻게 더해야 할지(+) 모르기 때문이다.
예를 들어, a < b 코드에서는, x 를 기준으로 비교할지, y 를 기준으로 비교할지 모른다.
따라서 이러한 연산자들을 써야 할 때는, 사용자가 직접 친절하게 컴퓨터한테 어떻게 연산해야 하는지 알려주어야 한다.
이것을 연산자 오버로딩 ( Operator Overloading ) 이라고 부른다.
구조체에만 있는 개념은 아니다. 하지만 주로 구조체에서 많이 쓰인다.
연산을 하는 두 구조체 값을 바꾸지 않는다는 가정 하에, 기본 틀은 아래와 같다.
아래 예시는, 이 틀에 맞추어 크기 비교 연산자 < 를 정의한 코드다.
( 이 예시에서 크기 비교 기준은 변수 x 의 값이다. )
위 코드를 이해해보자.
< 연산자는, < 를 기준으로 왼쪽에 있는 값이 오른쪽에 있는 값보다 작은가? 를 물어보는 것이다.
예를 들어 a < b 는, a 가 b 보다 작은가? 를 물어보는 것이 된다.
이 질문의 결과는 참 / 거짓, 즉 true / false 둘 중 하나다.
따라서 이 답의 자료형은 bool 이 됨을 알 수 있고, 그래서 bool 이 맨 앞에 적힌 것이다.
뒷부분의 코드들은 어쩔 수 없이 살짝의 암기가 들어갈 수 밖에 없다.
처음엔 보면서 따라쳐보고, 점차 외워보자. 어차피 앞으로 수도 없이 쓰게 되는 코드다.
Data 구조체 안에 < 연산자를 넣은 코드는 아래와 같다.
struct Data{
int x, y;
bool operator < ( const Data &Right ) const{
return x < Right.x;
}
}여기서 꼭 변수 이름이 Right 일 필요는 없다. 이해를 돕기 위해 붙인 이름이다.
앞서 말했 듯, < 연산자는, "자신과 자신의 오른쪽 변수(Right)" 를 비교하는 것이다.
따라서 변수 이름을 Right 라고 붙이면, 더 편하게 이해할 수 있다.
이 코드에서는, x 값을 기준으로 두 구조체를 비교하는 것이다.
return x < Right.x; 라는 것은, 자신의 x 값 ( x ) 과 자신의 오른쪽 변수의 x 값 ( Right.x ) 을 비교한다.
이렇게 < 연산자를 정의하면, if ( a < b ) 코드는 더 이상 에러가 나지 않는다. 컴퓨터는 이제 < 를 처리할 기준을 알기 때문이다.
그렇다면, 이를 응용하여 == 를 정의해보면?
== 도 마찬가지로, 나와 내 오른쪽 변수가 같은가? 를 물어보는 연산자다.
결과 값이 아까와 마찬가지로 참 / 거짓으로 나타나는 bool 일 것이다.
bool operator == ( const Data &Right ) const{
return x == Right.x && y == Right.y;
}위 코드는, 두 구조체의 x 와 y 가 둘 다 같아야만 두 구조체가 같다(==)고 판단하는 코드다.
마지막으로, + 연산자는 어떻게 정의할까?
만약 두 Data 변수를 더했을 때, x 는 x 끼리만, y 는 y 끼리만 더하고 싶다고 하자.
즉, ( 3, 5 ) + ( 1, 4 ) = ( 3 + 1 , 5 + 4 ) = ( 4 , 9 ) 가 되게 하고 싶은 것이다.
이 때는, 결과값이 자료형이 bool 이 아니다!
결과 값은 ( 4, 9 ) 이다. 즉 자료형이 Data 가 되는 것이다.
따라서 이 때는 맨 앞에 bool 이 아닌 Data 를 적어주면 된다.
Data operator + ( const Data &Right ) const{
return (Data){ x + Right.x , y + Right.y };
}<응용 문제>
두 int 변수 width, height 로 구성된 구조체 Rect(직사각형) 를 선언하자.
그리고 Rect 자료형의 변수 4개(a, b, c, d) 를 선언하자.
struct Rect{
int width, height;
}a, b, c, d;이제 main 함수에서는
a, b, c, d 의 width 와 height 를 각각 입력 받는다.
int main(){
scanf("%d %d", &a.width, &a.height);
scanf("%d %d", &b.width, &b.height);
scanf("%d %d", &c.width, &c.height);
scanf("%d %d", &d.width, &d.height);
}이후부터는 여러분들이 코드를 완성해야 한다.
a + b 직사각형과 c + d 직사각형의 넓이를 비교할 것이다.
두 직사각형을 더하면, width 끼리 더해지고 height 끼리 더해진다.
즉 Rect 의 정보를 (width, height) 로 표현했을 때, a = (4, 8) 이고 b = (1, 2) 라면 a + b = (5, 10) 이 된다.
(a + b) 직사각형의 넓이가 더 작다면 Left Small 를,
(c + d) 직사각형의 넓이가 더 작다면 Right Small 를,
두 직사각형의 넓이가 같다면 Same 을 출력하자.
즉, 크기 비교 기준이 넓이인 것이다.
반드시 실력 향상을 위해 +, <, == 등의 연산자를 Rect 구조체 안에 넣어서 풀어보자.
직사각형의 넓이는 당연히 width * height 일 것이다.
예시 모범 코드의 전반적인 틀은 아래와 같을 것이다.
if(a + b == c + d) // Same 출력
else if(a + b < c + d) // Left Small 출력
else // Right Small 출력입력
4줄에 걸쳐 a, b, c, d 의 width 와 height 가 입력된다.
이들은 모두 10000 이하의 자연수다.
출력
문제에서 요구한 대로 비교하여 결과값을 출력하라.
예제 #1
3 6
2 3
1 1
2 14
Same
a + b = (5, 9)
c + d = (3, 15)
두 직사각형의 넓이는 45로 동일하다.
예제 #2
1 2
3 4
1 3
2 4
Right Small
a + b = (4, 6)
c + d = (3, 7)
c + d 의 넓이가 더 작다.
예제 #3
2 5
4 1
2 3
3 5
Left Small
a + b = (6, 6)
c + d = (5, 8)
a + b 의 넓이가 더 작다.