QT/Win32 Q_DECLARE_FLAGS 매크로
페이지 정보
작성자
본문
파스칼 언어에는 열거형 상수들을 집합으로 표현하는 집합변수(?)라는게 있습니다. 정확한 명칭은 모르겠습니다. ;;
표현법이 어떠하던간에 C 계열에서는 비트연산의 한 방법인거죠. 쓰기에 따라 코드가 간결해지는 장점이 있습니다.
flag라 하는데요. Qt에서 프로그래머에게 코딩에 편리함을 주게끔 정해놓은 것이 Q_DECLARE_FLAGS 매크로죠.
대표적으로 QWidget::setWindowFlags(Qt::WindowFlags)에 들어가는 Qt::WindowFlags가 요렇게 되어있습니다.
#ifndef SOMEOBJECT_H
#define SOMEOBJECT_H
#include <QObject>
class SomeObject : public QObject
{
Q_OBJECT
public:
SomeObject(QObject* parent = 0) : QObject(parent) {
}
enum SOMEFLAG {
FLAG_00 = 0x00,
FLAG_0A = 0x01,
FLAG_0B = 0x02,
FLAG_A0 = 0x10,
FLAG_B0 = 0x20
}
Q_DECLARE_FLAGS(SOMEFLAG_S, SOMEFLAG) //--[1]
signals:
void flagChanged();
private:
SOMEFLAG_S m_flags; //--[2]
//...
public:
SOMEFLAG_S flags() const { return m_flags; }
};
Q_DECLARE_OPERATORS_FOR_FLAGS(SomeObject::SOMEFLAG_S) //--[3]
#endif SOMEOBJECT_H
--[1] : SOMEFLAG_S라는 flags형태의 타입을 선언하는데 열거형 SOMEFLAG를 지정해줍니다.
--[2] : 이제 SOMEFLAG_S라는 SOMEFLAG의 enum 항목들을 집합으로 갖는 flags형을 선언할 수 있습니다.
--[3] : SOMEFLAG_S로 선언된것을 (int)같은 캐스트연산자없이 바로 비트연산이 가능하도록 해줍니다.
m_flags &= ~FLAG_0A;
if(someObject->flags() & SomeObject::FLAG_0A) ...;
이런식으로 코드를 작성할 수 있게 되죠.
이게.. 잘못 기억했었는지는 몰라도 예전엔 안그랬던거 같은데 5.3.1에서는 Q_DECLARE_OPERATORS_FOR_FLAGS
없이 Q_DECLARE_FLAGS로 정의만 해놓으면 비트연산이 되네요
위의 매크로들의 도움없이 enum형 그대로 flag식 코딩을 한다면 성격이 좀 급하신분은 제법 짜증나실 겁니다.
SomeObject::SOMEFLAG flag = (SomeObject::SOMEFLAG)((int)flag & ~(int)SomeObject::FLAG_0A);
=> SomeObject::SOMEFLAG_S flags &= ~SomeObject::FLAG_0A;
꼭 알아둘 필요까지는 없는 매크로이지만 코딩작업이 편해지죠 ^^
표현법이 어떠하던간에 C 계열에서는 비트연산의 한 방법인거죠. 쓰기에 따라 코드가 간결해지는 장점이 있습니다.
flag라 하는데요. Qt에서 프로그래머에게 코딩에 편리함을 주게끔 정해놓은 것이 Q_DECLARE_FLAGS 매크로죠.
대표적으로 QWidget::setWindowFlags(Qt::WindowFlags)에 들어가는 Qt::WindowFlags가 요렇게 되어있습니다.
#ifndef SOMEOBJECT_H
#define SOMEOBJECT_H
#include <QObject>
class SomeObject : public QObject
{
Q_OBJECT
public:
SomeObject(QObject* parent = 0) : QObject(parent) {
}
enum SOMEFLAG {
FLAG_00 = 0x00,
FLAG_0A = 0x01,
FLAG_0B = 0x02,
FLAG_A0 = 0x10,
FLAG_B0 = 0x20
}
Q_DECLARE_FLAGS(SOMEFLAG_S, SOMEFLAG) //--[1]
signals:
void flagChanged();
private:
SOMEFLAG_S m_flags; //--[2]
//...
public:
SOMEFLAG_S flags() const { return m_flags; }
};
Q_DECLARE_OPERATORS_FOR_FLAGS(SomeObject::SOMEFLAG_S) //--[3]
#endif SOMEOBJECT_H
--[1] : SOMEFLAG_S라는 flags형태의 타입을 선언하는데 열거형 SOMEFLAG를 지정해줍니다.
--[2] : 이제 SOMEFLAG_S라는 SOMEFLAG의 enum 항목들을 집합으로 갖는 flags형을 선언할 수 있습니다.
--[3] : SOMEFLAG_S로 선언된것을 (int)같은 캐스트연산자없이 바로 비트연산이 가능하도록 해줍니다.
m_flags &= ~FLAG_0A;
if(someObject->flags() & SomeObject::FLAG_0A) ...;
이런식으로 코드를 작성할 수 있게 되죠.
이게.. 잘못 기억했었는지는 몰라도 예전엔 안그랬던거 같은데 5.3.1에서는 Q_DECLARE_OPERATORS_FOR_FLAGS
없이 Q_DECLARE_FLAGS로 정의만 해놓으면 비트연산이 되네요
위의 매크로들의 도움없이 enum형 그대로 flag식 코딩을 한다면 성격이 좀 급하신분은 제법 짜증나실 겁니다.
SomeObject::SOMEFLAG flag = (SomeObject::SOMEFLAG)((int)flag & ~(int)SomeObject::FLAG_0A);
=> SomeObject::SOMEFLAG_S flags &= ~SomeObject::FLAG_0A;
꼭 알아둘 필요까지는 없는 매크로이지만 코딩작업이 편해지죠 ^^
추천2
댓글목록
devilqoo님의 댓글

한번 정리하고 싶은 내용이었는데 잘 보고 갑니다. :)
나무나무나무님의 댓글

무척이나 편리한 기능이네요!
이런 기능이 없어서 따로 라이브러리를 만들어 두고 vector 자료형에 문자열을 담아 처리하도록 했던 과거가 안타까워집니다... qt만세!