살군의 보조기억 장치

Another memory device…

<< 연산자 오버로딩 – ts_func.cpp

leave a comment »

이전 포스트에서 ts.hpp 를 봤었는데, 여기에서 << 연산자 오버로딩의 내용을 살펴보자. 이를 살펴보려면 우선 MatInfo가 무엇인지를 봐야된다.

struct CV_EXPORTS MatInfo
{
    MatInfo(const Mat& _m) : m(&_m) {}
    const Mat* m;
};

이런… 시작하자마자 암호같은 코드가 나왔다. line:160 은 도데체 무슨말일까? struct 타입인데 생성자 처럼 생긴 뭔가가 있고 거기에 콜론과 중괄호 까지 같이 쓰고 있다. 역시나 stackoverflow 에 질문한 사람도 있고 친절하게 답한 사람도 있다.

In C++ the only difference between a class and a struct is that members and base classes are by default private in classes, while in structs they default to public. So structures can have constructors, and the syntax is the same as for classes.

struct TestStruct { 
        int id;
        TestStruct() : id(42) { }
};

아! 이런 이건 예전에 봤던 거였네. 좀처럼 볼 일이 없는 형식이라 까먹고 있었다. 다시보면, MatInfo 는 matrix 포인터를 가지는 구조체이다. 그 이상의 기능도 없다. 그럼 왜 이렇게 할까? 이유를 잘 모르겠다. matrix 변경을 막으려고 한다면 포인터 변경을 막는 const 도 추가해야 되기 때문이다. 지금의 상태는 값 변환은 못하도록 막지만, 포인터 자체가 변할 경우에는 그대로 변경이 되기 때문이다. 이건 실제 사용코드를 봐야되니까 다음 기회에 찾아봐야겠다.

std::ostream& operator << (std::ostream& out, const MatInfo& m) 
{     
    if( !m.m || m.m->empty() )
        out << "";
    else
    {
        static const char* depthstr[] = {"8u", "8s", "16u", "16s", "32s", "32f", "64f", "?"};
        out << depthstr[m.m->depth()] << "C" << m.m->channels() << " " << m.m->dims << "-dim (";
        for( int i = 0; i < m.m->dims; i++ )
            out << m.m->size[i] << (i < m.m->dims-1 ? " x " : ")");
    }
    return out;
}

위는 ts_func.cpp 에서 연산자 오버라이딩을 실제 구현한 코드이다. 대충 살펴보면 matrix 정보에서 depth, channel, dim 등을 표시하는 거다.

<< 연산자는 이전글에서 설명한 것 같이 bitwise 연산을 위한 연산자 오버로딩도 있지만, 여기서 사용한 방식은 출력 연산자 오버로딩이다. 즉, ostream 의 출력방식을 전역으로 처리한 것이다. 마침 내가 햇갈리던 부분을 잘 설명한 글이 있어 그대로 인용한다.

메인함수를 보자. 어떤 Point 클래스가 있고, 이 Point 클래스를 p라는 객체를 통해 생성하고 있고, 이 객체를 cout을 이용해 출력하려는 문장이다. 하지만 기본적으로 cout은 기본자료형만 출력을 하지 객체인 사용자 타입의 자료형은 출력을 할 수가 없다. 4번째 줄을 멤버 함수로의 오버로딩 해석에 의해 풀어 써 보자.
 cout.operator<< (p) 즉, p객체를 인자값을 받을 수 있도록 cout 객체에는 operator<< 연산자가 오버로딩 되어 있어야 하는데, 표준 std의 ostream 클래스에서도 쉬프트 연산에 대한 오버로딩이 정의 되어 있지 않다. 그래서 우리가 표준 라이브러리를 건드리면서까지 객체를 출력하는 일은 불가능 할 것이다.

이로서 멤버 함수로의 오버로딩으로는 객체를 출력할 수 없다는 것을 알 수 있었다. 그럼 전역 함수의 오버로딩을 보자.전역함수로의 오버로딩에서는 cout << p 문장은 operator (cout, p); 로 풀어 써지고, 이것은 논리적으로 문제가 없다. 그럼 전역함수로 오버로딩으로 다음과 같이 함수를 정의 할 수 있겠다.

기존의 오버로딩은 functionName.operator() 형식이였는데, 출력연산자의 경우에는 위 코드의 line:2790 처럼 항상 std::ostream& operator << (std::ostream& out, const paramType& param) 이 되는 것이다. 실제 cout 을 호출할 때를 생각하면 전달 parameter 가 하나밖에 없게 되는 부분이 좀 이해가 안됐는데, 위의 글에서 명쾌하게 해결이 되었다.

참고
Advertisements

Written by gomiski

2014/02/13 at 6:40 am

Posted in C++, Lecture, opencv

Tagged with , , , ,

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: