<개인공부>/[C++]

[C++] map, set의 키를 클래스 구조체로 만드는 방법

BlockDMask 2019. 11. 20. 00:50
반응형

안녕하세요. BlockDMask 입니다.

여러분 std::map, std::set 아시죠? key값을 이용서 데이터를 저장하는 container 이잖아요.

혹시 map, set의 공부가 필요하시다면 여기 링크를 타고 다녀오셔도 좋습니다.

[std::map], [std::set]

여러분은 map과 set의 key값을 어떤걸로 쓰고 계셨나요? string? int? float?

네 맞습니다. 우리는 이렇게 기본적인 데이터 타입을 key값으로 쓰고 있었습니다.

하지만, 바로 오늘! 이 포스트를 보고 난 후! 부터는 

C++ 맵, 셋에서 key값class, struct 우리가 직접 만든 타입(user defined type)으로 쓸수 있을것입니다.

std::map, std::set에서 키값을 일반 타입 string, int 등등이 아니라 user defined type으로 사용할 수 있는 방법! 바로 들어가시죠.


<목차>

1. 클래스, 구조체를 map, set의 키값으로 만드는 방법.

2. map, set의 키값을 구조체 클래스로 가지는 예제.


1. 클래스, 구조체를 map, set의 키값으로 만드는 방법.


 무엇을 추가하면 map, set의 키값에 클래스 구조체를 넣을수 있을까?


map, set을 생각해보면 균형 이진트리로 구현되어 있는 연관 컨테이너 입니다.

그 트리에서 find의 결정적인 역할을 하는게 바로 KEY 입니다.


이 key값은 이진트리에서 탐색을 할 수 있는 조건이 되어야하는데요.

그렇기 때문에 대소비교 가능해야합니다.


클래스들을 <, > 기호를 통해서 대소비교가 가능하게 할수 있는 방법. 무엇이 있을까요?

네 맞습니다. operator가 있습니다.


바로바로 operator < 를 재정의 해주기만 하면 map, set의 key값으로 class, struct를 사용할 수 있습니다.!


▶  클래스나 구조체 내부에 operator< 를 재정의 하는 방법

클래스, 구조체 내부에 아래와 같이 정의 및 선언합니다.

반환형은 bool 타입이고, 매개변수로는 현재 클래스와 동일한 클래스 타입으로 const & 형태로 받습니다.


bool operator<(const 클래스명& 변수명) const

{

//비교구문을 통해 true, false를 반환.

}


예를들어 아래와 같은 클래스가 있다고 가정하면 이렇게 operator를 재정의 하시면 됩니다.

class Human

{

private:

int age;

int height;

public:

Human(int _age, int _height) : age(_age), height(_height){}

bool operator<(const Human& rhs) const

{

if (age != rhs.age)                //age 먼저 비교

{

return age < rhs.age;

}

return height < rhs.height;    // age가 같으면 height 비교.

}

}



2. map, set의 키값을 구조체 클래스로 가지는 예제.


map의 key가 클래스인 예제.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include<iostream>
#include<map>        //map
#include<utility>    //make_pair
using namespace std;
class Human
{
private:
    int age;
    int height;
public:
    Human(int _age, int _height) : age(_age), height(_height){}
    bool operator<(const Human& rhs) const    //이게 핵심!
    {
        if (age != rhs.age)
        {
            return age < rhs.age;
        }
 
        return height < rhs.height;
    }
};
 
int main(void)
{
    std::map<Human, int> m;    //map 선언
 
    Human hArr[] = { Human(30180), Human(30170), Human(30160),
                     Human(22110), Human(22100), Human(42168),
                     Human(51170) };        //map의 key 값이될 클래스 배열
 
    int num = 0;                            //map의 value가 될 아무값.
    for (Human human : hArr)
    {
        m.insert(make_pair(human, num));    //클래스가 map의 키 값으로 잘 들어가네요?
        num++;
    }
 
    if (m.find(Human(30160)) != m.end())    //map의 키값 검색이 잘되네요?
    {
        cout << "map에 Human(30, 160)이 있소." << endl;
    }
    else
    {
        cout << "map에 Human(30, 160)은 없소." << endl;
    }
    return 0;
}
cs


결과

opeator< 가 재정의된 Human클래스가 map의 키값으로 잘 들어가있는걸 확인할 수 있습니다.



▶  만약에 operator<가 없는 클래스를 키값으로 쓰려고 하면 아래와 같이 컴파일 에러가 나게 됩니다.


이렇게 오늘은 "map에 키값으로 클래스"를 넣는 방법에 대해 알아보았습니다. 궁금한점이나

C++에 대해서 특정한게 알고싶다 하시는 분은 댓글 편하게 달아주세요.

반응형