(Qt : basic) Q_D Macro

Posted by : at

Category : Qt



우선 이걸 먼저 알아야한다.

// Myclass.h
class Myclass
{
public:
    Myclass() {}
    ~Myclass() {}

    // some func

private:
    int m_data1;
};

처음에 이러한 Myclass클래스가 있었다 가정해보자.
사용중 어떠한 이유로 멤버 데이터를 확장해야할 일이 생겼다.

// Myclass.h
class Myclass
{
public:
    Myclass() {}
    ~Myclass() {}

    // some func

private:
    int m_data1;
    std::string m_string1;
    // ... (엄청 많다고 가정)
};

이게 효율적일까?
당연하지만 비효율적 -> Myclass.h를 참조하는 모든 cpp에서 컴파일시 수정이 필요

개선하는 방법은 간단하다. 멤버변수를 다른곳에 옮겨두면된다.

class Myclass
{
public:
    Myclass() : d_ptr(new MyclassPrivate) {}
    ~Myclass() {}

    // some func
protected:
    MyclassPrivate *d_ptr;
};
struct MyclassPrivate
{
    int m_data1;
    std::string m_string1;
    // ... (엄청 많다고 가정)
};

예를들어서 m_data1에 접근한다면

class Myclass
{
public:
    Myclass() : d_ptr(new MyclassPrivate) {}
    ~Myclass() {}

    // 이렇게 접근가능
    int getMydata1() { return d_ptr->m_data1; }

    // some func
protected:
    MyclassPrivate *d_ptr;
};

멀리왔다… 그래서 Q_D, Q_Q를 왜쓰는데?

선언은 아래와 같이 되어있다.

#define Q_D(Class) Class##Private * const d = d_func()
#define Q_Q(Class) Class * const q = q_func()

문제는 뭐냐? d_ptr를 쓰는 클래스가 d_ptr를 쓰는 부모클래스를 상속해버리는 경우가 발생한다.

class MyclassBase
{
public:
    MyclassBase() : d_ptr(new MyclassBasePrivate) {}
    ~MyclassBase() {}

    // some func
protected:
    MyclassBasePrivate *d_ptr;
};
class MyclassDerived
{
public:
    MyclassDerived() : d_ptr(new MyclassDerivedPrivate) {}
    ~MyclassDerived() {}

    int getMyData() { 
        // 컴파일러 입장에서 d_ptr가 MyclassDerived인지 MyclassBase인지 구분 불가능
        return d_ptr->mydata; 
        }

    // some func
protected:
    MyclassDerivedPrivate *d_ptr;
};

캐스팅을 새로할까?

int getMyData() 
{ 
    // 매번 이걸한다고?? -> Q_D, Q_Q를 사용하자
    MyclassDerivedPrivate* d = static_cast<MyclassDerivedPrivate>(d_ptr);
    return d->mydata; 
}

class MyclassDerived
{
    Q_DECLARE_PRIVATE(MyclassDerived)   // Q_Q를 쓰기위해서 선언

public:
    MyclassDerived() : d_ptr(new MyclassDerivedPrivate) {}
    ~MyclassDerived() {}

    int getMyData() 
    { 
        // good!
        Q_D(MyclassDerived)
        return d->mydata; 
    }

    // some func
protected:
    MyclassDerivedPrivate *d_ptr;
};

About Taehyung Kim

안녕하세요? 8년차 현업 C++ 개발자 김태형이라고 합니다. 😁 C/C++을 사랑하며 다양한 사람과의 협업을 즐깁니다. ☕ 꾸준한 자기개발을 미덕이라 생각하며 노력중이며, 제가 얻은 지식을 홈페이지에 정리 중입니다. 좀 더 상세한 제 이력서 혹은 Private 프로젝트 접근 권한을 원하신다면 메일주세요. 😎

Star
Useful Links