방금 Qt를 사용하기 시작했으며 모든 예제 클래스 정의에 매크로 Q_OBJECT
가 첫 번째 줄로 있음을 알았 습니다. 이 전 처리기 매크로의 목적은 무엇입니까?
방금 Qt를 사용하기 시작했으며 모든 예제 클래스 정의에 매크로 Q_OBJECT
가 첫 번째 줄로 있음을 알았 습니다. 이 전 처리기 매크로의 목적은 무엇입니까?
답변:
로부터 Qt는 문서 :
Meta-Object Compiler (moc)는 Qt의 C ++ 확장을 처리하는 프로그램입니다.
moc 도구는 C ++ 헤더 파일을 읽습니다. Q_OBJECT 매크로를 포함하는 하나 이상의 클래스 선언을 찾으면 해당 클래스의 메타 오브젝트 코드를 포함하는 C ++ 소스 파일을 생성합니다. 무엇보다도 신호 및 슬롯 메커니즘, 런타임 유형 정보 및 동적 속성 시스템에는 메타 객체 코드가 필요합니다.
Q_OBJECT::connect()
것이 아니라 오히려 그럴까요 connect()
?
그것은 단지이 클래스에 gui 요소가 있고 'moc'를 통해 실행되어야한다고 프리 컴파일러에게 알려줍니다. 신호 / 슬롯 메커니즘을 사용하는 클래스에만 이것을 추가하면됩니다.
그러나 다른 클래스에서는 조용히 무시됩니다. 빌드 시간 만 추가됩니다.
Q_OBJECT
넘김 qobject_cast
과 성찰. 그것은 당혹스러운 행동으로 이어질 수 있으므로 나쁜 생각입니다.
Q_OBJECT
다른 QObject
클래스가 아닌 클래스 에서 "조용히"무시되는 것은 사실이 아닙니다 . C ++ 표준에 따르면 정의되지 않은 여러 멤버 함수 및 변수를 선언하여 정의되지 않은 동작을 도입합니다. 또한 클래스의 네임 스페이스를 QObject
특정 멤버로 오염시킵니다 . 예 Q_OBJECT
를 들어 a라는 메소드를 포함하는 관련없는 클래스를 깨뜨릴 수 있습니다 metaObject
.
Q_OBJECT
매크로 를 장착하려고하지만 매크로가없는 gui 클래스뿐만 아니라 매크로가 아닌 gui 클래스를 갖는 것이 완벽합니다. 이 매크로는 유용하지만 GUI 클래스에 제한되거나 필요하지 않습니다.
MOC (메타 개체 컴파일러)는 Q_OBJECT 매크로 포함 헤더 파일을 C ++ 해당 소스 코드로 변환합니다. 기본적으로 신호 슬롯 메커니즘을 제어하고 C ++ 컴파일러가 이해할 수있게합니다.
Q_OBJECT
매크로는 컴파일러에 의해 확장되며 moc는 필요하지 않습니다. moc는 매크로 자체로는 아무 것도하지 않지만 , 매크로가 선언 한 멤버 변수 및 메소드 의 정의 를 생성합니다 . Q_OBJECT
1 Meta-Object System 의 Qt 문서에서
moc 도구는 C ++ 소스 파일을 읽습니다. Q_OBJECT 매크로를 포함하는 하나 이상의 클래스 선언을 찾으면 해당 클래스 각각에 대한 메타 오브젝트 코드를 포함하는 다른 C ++ 소스 파일을 생성합니다. 이 생성 된 소스 파일은 클래스의 소스 파일에 #include되거나 더 일반적으로 클래스의 구현과 컴파일 및 링크됩니다.
2 Q_OBJECT의 Qt 문서에서
Q_OBJECT 매크로는 자체 신호와 슬롯을 선언하거나 Qt의 메타 객체 시스템이 제공하는 다른 서비스를 사용하는 클래스 정의의 private 섹션에 나타나야합니다.
3 moc의 Qt 문서에서
moc 도구는 C ++ 헤더 파일을 읽습니다. Q_OBJECT 매크로를 포함하는 하나 이상의 클래스 선언을 찾으면 해당 클래스의 메타 오브젝트 코드를 포함하는 C ++ 소스 파일을 생성합니다. 무엇보다도 신호 및 슬롯 메커니즘, 런타임 유형 정보 및 동적 속성 시스템에는 메타 객체 코드가 필요합니다.
4 신호 및 슬롯에 대한 Qt 문서에서
Q_OBJECT 매크로는 moc에 의해 구현되는 여러 멤버 함수를 선언하기 위해 전처리기에 의해 확장됩니다. "LcdNumber에 대한 vtable에 대한 정의되지 않은 참조"행에 컴파일러 오류가 발생하면 moc을 실행하거나 링크 명령에 moc 출력을 포함하는 것을 잊었을 수 있습니다.
gcc에서는 -E
확장 매크로를 볼 수 있습니다. 이것이 Q_OBJECT
Linux의 gcc에서 확장되는 것입니다. 이는 플랫폼에 따라 다를 수 있으며 QT 버전에 따라 변경 될 수 있습니다. moc 컴파일러의 태그가 아니라는 것을 알 수 있습니다.
# 11 "mainwindow.hh"
#pragma GCC diagnostic push
# 11 "mainwindow.hh"
# 11 "mainwindow.hh"
#pragma GCC diagnostic ignored "-Wsuggest-override"
# 11 "mainwindow.hh"
static const QMetaObject staticMetaObject; virtual const QMetaObject *metaObject() const; virtual void *qt_metacast(const char *); virtual int qt_metacall(QMetaObject::Call, int, void **); static inline QString tr(const char *s, cons
t char *c = nullptr, int n = -1) { return staticMetaObject.tr(s, c, n); } __attribute__ ((__deprecated__)) static inline QString trUtf8(const char *s, const char *c = nullptr, int n = -1) { return staticMetaObject.tr(s, c, n); } private:
# 11 "mainwindow.hh"
#pragma GCC diagnostic ignored "-Wattributes"
# 11 "mainwindow.hh"
__attribute__((visibility("hidden"))) static void qt_static_metacall(QObject *, QMetaObject::Call, int, void **);
# 11 "mainwindow.hh"
#pragma GCC diagnostic pop
# 11 "mainwindow.hh"
struct QPrivateSignal {};
Q_OBJECT 매크로는 자체 신호와 슬롯을 선언하거나 Qt의 메타 객체 시스템이 제공하는 다른 서비스를 사용하는 클래스 정의의 private 섹션에 나타나야합니다.
Q_OBJECT
매크로는에서 파생 된 모든 클래스에 나타나야합니다 QObject
. 매크로가 없으면 코드가 미묘하게 손상되며 컴파일이 발생해도 코드가 제대로 작동하지 않습니다.
Q_OBJECT
매크로가 누락 되면 컴파일되지만 작동하지 않는 코드의 예가 있습니까?
Q_OBJECT
액세스 지정자를 사용한다는 것을 알 수 있습니다. 그래서 매크로는 아래에 표시해야하는지 여부 private
, protected
또는 public
지정자는 무관하다 -이 클래스의 선두에 배치 그냥 컨벤션입니다.