본문 바로가기
컴퓨터/C++_STL

에지(edge) 객체 구현해 보기

by adnoctum 2010. 5. 8.



   노드와 노드를 잇는 선분(edge)를 표현하는 객체를 나타내기 위한 class 를 작성해 본다. edge를 STL의 set이나 map 에 넣기 위하여 operator< 를 정의하며, 또한 operator== 역시 정의해 본다.

   class edge 의 attribute으로는 std::string 으로 표현하는 두 개의 노드만을 갖는다. operation 으로는 생성자류, 파괴자, operator <, =, ==, 그리고 attribute인 두 노드를 반환하는 함수를 정의해 보자. 헤더 파일은 다음과 같다.


#ifndef __DEFINITION_OF_EDGE__

#define __DEFINITION_OF_EDGE__

 

#include <string>

 

class edge{

private:

        std::string _node1;

        std::string _node2;

 

public:

        edge();

        edge(const std::string& n1, const std::string& n2);

        edge(const edge& e);

        std::string first() const;

        std::string second() const;

        bool operator<(const edge& e)const ;

        bool operator==(const edge& e) const ;

        edge& operator=(const edge& e);

        virtual ~edge();

 

        std::pair<std::string,std::string> get_node_pair() const ;

};

 

#endif


복사 생성자라던가 attribute을 반환하는 함수는 다음과 같은데 너무 뻔하므로 다음으로 넘어 가자.


   operator== 및 operator= 는 다음과 같이 정의할 수 있을 것이다.

bool edge::operator==(const edge& e) const {

        if(_node1 == "" || _node2 == "") return false;

        if(_node1 == e._node1 && _node2 == e._node2) return true;

        if(_node1 == e._node2 && _node2 == e._node1) return true;

        return false;

}

edge& edge::operator=(const edge& e){

        if(*this == e) return *this;

        _node1 = e._node1;

        _node2 = e._node2;

        return *this;

}


    operator== 는 parameter로 edge 객체를 받는데, 함수 내부에서 parameter로 받은 edge 객체를 수정하지 않을 것으므로 const 로 받는다. 아무래도 node를 표현하는 string 타입의 identifier가 그리 크지는 않을테지만 string 이므로 메모리를 많이 잡아먹을 수 있다는 가정이 들어 가며, 그 경우 call by value로 호출하게 되면 조금 부담이 될 수 있다. 그러므로 const 로 받는다. 또한 operator== 는 함수 내부에서 edge class의 유일한 attribute인 [_node1]과 [_node2]를 변경시키지 않을 것이므로 member function 자체도 const로 선언한다. 하는 기능은 다소 직관적인데, 현재 구현하는 것이 방향성이 없는 edge 이므로 두 노드가 순서에 상관없이 같으면 참을 반환한다. 논리에 따라 parameter로 받은 e 역시 빈 노드를 가지면 거짓이 반환됨을 알 수 있다.

   operator= 는 역시 직관적이다. 단 이 경우 operator== 와는 달리 현 객체의 attribute인 두 노드의 값을 수정하기 때문에 operator= 는 const 가 아니다.

   다음으로는 가장 난해한 operator< 를 구현해 보자. 이 함수를 구현해야 edge type으로 된 변수들을 STL의 set 이나 map 에 집어 넣을 수 있으므로 잘 정의해야 한다. 현재는 단지 ordering 만 잘 하면 되는 것일 뿐 여기서 정의한 '크다'라는 것이 별다른 의미를 지니지 않으므로 STL의 spec에서 요구한 조건인 strict weak ordering만 되도록 하면 된다.

bool edge::operator<(const edge& e) const {

 

        const std::string& max1 = (_node1 > _node2 ? _node1 : _node2);

        const std::string& max2 = (e._node1 > e._node2 ? e._node1 : e._node2);

 

        if(max1 == max2){

                const std::string& min1 = (_node1 < _node2 ? _node1 : _node2);

                const std::string& min2 = (e._node1 < e._node2 ? e._node1 : e._node2);

                return min1 < min2;

        }

        return max1 < max2;

}


위 정의는, 노드의 값 중 큰 값을 갖는 edge 형 변수가 크다는 정의이다. 만약 두 값중 큰 노드의 값이 같다면 작은 값이 큰 변수가 크다고 할 수 있다. 이와 같이 정의된 opeartor< 는 strict weak ordering 이 되기 때문에 STL의 map과 set에 집어 넣을 수 있게 된다.

참고글
1. no match for ‘operator<’ in ‘__x < __y’
2. strict weak ordering