페이지가 로드되지 않나요? 여기를 눌러보면 고쳐질 수도 있어요.
Placeholder

#8576

Tutorial : 구조체 연산자 오버로딩 2s 1024MB

문제

두 정수 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 의 넓이가 더 작다.



출처

againalgo

로그인해야 코드를 작성할 수 있어요.