2015. 8. 8. 22:29

The Meta-Object System 소개

The Meta-Object System

메타-오브젝트 시스템

출처 : http://doc.qt.io/qt-4.8/metaobjects.html

Qt's meta-object system provides the signals and slots mechanism for inter-object communication, run-time type information, and the dynamic property system.

Qt 의 메타-오브젝트 시스템은 객체-간 통신, 실행-중 (런타임) 자료 형 정보, 다이나믹 프로퍼티 시스템을 위한 시그널과 슬롯을 제공합니다.

The meta-object system is based on three things:

메타-오브젝트 시스템은 다음의 3가지에 근간(기본) 합니다.

  1. The QObject class provides a base class for objects that can take advantage of the meta-object system.

    QObject 클래스는 메타-오브젝트 시스템의 이점을 활용하는 객체들에 대한 기본(부모) 클래스를 제공합니다. 
  2. The Q_OBJECT macro inside the private section of the class declaration is used to enable meta-object features, such as dynamic properties, signals, and slots.

    Q_OBJECT 매크로는 다이나믹 프로퍼티(동적 속성), 시그널과 슬롯과 같은 매타-오브젝트 특성을 활성화 하는데 사용되는 클래스 선언의 프라이빗 영역에 존재합니다.
  3. The Meta-Object Compiler (moc) supplies each QObject subclass with the necessary code to implement meta-object features.

    메타-오브젝트 컴파일러 (moc) 는 메타-오브젝트 기능을 구현하는데 필요한 코드를 포함하는 QObject 의 자식 클래스를 각각 제공합니다.  

The moc tool reads a C++ source file. If it finds one or more class declarations that contain the Q_OBJECT macro, it produces another C++ source file which contains the meta-object code for each of those classes. This generated source file is either #include'd into the class's source file or, more usually, compiled and linked with the class's implementation.

moc 도구는 C++ 소스 파일을 읽습니다. 만약 하나 이상의 클래스가 Q_OBJECT 를 선언했다고 확인이 되면, 각 클래스에 대해 메타-오브젝트 코드를 포함하는 또다른 C++ 소스 파일을 생성합니다. 이 작성된 파일은 #include 형태로 클래스의 소스 파일에 포함되거나, 또는 더 일반적으로, 클래스의 구현부와 맞물려서 컴파일, 링크 과정을 거치게 됩니다.

In addition to providing the signals and slots mechanism for communication between objects (the main reason for introducing the system), the meta-object code provides the following additional features:

객체들 간 (본 시스템을 소개하는 핵심 이유) 통신을 하는 시그널과 슬롯 메커니즘을 제공하는 것과 추가하여 메타-오브젝트 코드는 다음의 추가적인 기능을 제공합니다.

  • QObject::metaObject() returns the associated meta-object for the class.
  • QObject::metaObject() 는 해당 클래스와 연관된 메타-오브젝트를 반환합니다.
  • QMetaObject::className() returns the class name as a string at run-time, without requiring native run-time type information (RTTI) support through the C++ compiler.
  • QMetaObject::className() 는 C++ 컴파일러가 지원하는 네이티브 런타-임 (실행-중) 형 정보를 요청하지 않고도, 실행-중에 클래스 이름을 반환해 줍니다. (자체적으로 RTTI 기능 지원)
  • QObject::inherits() function returns whether an object is an instance of a class that inherits a specified class within the QObject inheritance tree.
  • QObject::inherits() 는 QObject 상속 구조 내에 지정한 클래스의 객체가 무엇인지 반환해주는 함수 입니다.
  • QObject::tr() and QObject::trUtf8() translate strings for internationalization.
  • QObject::tr() 과 QObject::trUtf8() 은 다국어용으로 문자열을 번역(변환) 합니다.
  • QObject::setProperty() and QObject::property() dynamically set and get properties by name.
  • QObject::setProperty() 와 QObject::property() 는 이름을 사용해서 속성값을 동적으로 가져오거나 지정합니다.
  • QMetaObject::newInstance() constructs a new instance of the class.
  • QMetaObject::newInstance() 는 해당 클래스의 새로운 인스턴스 (객체) 를 생성합니다.

It is also possible to perform dynamic casts using qobject_cast() on QObject classes. The qobject_cast() function behaves similarly to the standard C++ dynamic_cast(), with the advantages that it doesn't require RTTI support and it works across dynamic library boundaries. It attempts to cast its argument to the pointer type specified in angle-brackets, returning a non-zero pointer if the object is of the correct type (determined at run-time), or 0 if the object's type is incompatible.

QObject 클래스의 qobject_cast() 를 사용하여 다이나믹 캐스트를 수행할 수 있습니다. qobject_cast() 는 표준 C++ dynamic_cast() 와 유사하게 동작하면서도 RTTI 지원을 요청하지 않고도 동적 라이브러리 경계점(바운더리)들과 같이 작동합니다. 그것 (qobject_cast 연산자) 은 꺽쇠-괄호 (< >) 연산자에 표시된 포인터 형을 인수로 받아서, 정확한 형태의 객체 (실행-중에 판단) 라면 0 이 아닌 포인터를 반환하고, 호환이 되지 않는 객체형이라면 0을 반환합니다.

For example, let's assume MyWidget inherits from QWidget and is declared with the Q_OBJECT macro:

예를 들어, QWidget 을 상속 받은 MyWidget 이 있고, 이는 Q_OBJECT 매크로로 선언이 되었다고 가정합니다.

    QObject *obj = new MyWidget;

The obj variable, of type QObject *, actually refers to a MyWidget object, so we can cast it appropriately:

obj 변수는 QObject* 형으로, 실제로는 MyWidget 객체를 참조합니다. 그렇기 때문에 우리는 적절히 캐스트 (변환) 을 할 수 있습니다

    QWidget *widget = qobject_cast<QWidget *>(obj);

The cast from QObject to QWidget is successful, because the object is actually a MyWidget, which is a subclass of QWidget. Since we know that obj is a MyWidget, we can also cast it to MyWidget *:

실제로 MyWidget 은 QWidget 의 자식 클래스이므로, QObject 에서 QWidget 으로 캐스트 동작이 성공적으로 이뤄졌습니다. 우리는 obj 가 MyWidget 로 알고 있으므로, MyWidget * 을 사용해서 캐스트를 할 수 있습니다.

    MyWidget *myWidget = qobject_cast<MyWidget *>(obj);

The cast to MyWidget is successful because qobject_cast() makes no distinction between built-in Qt types and custom types.

qobject_cast() 가 내장-된 Qt 형식과 사용자 지정 형식 간에 특별한 차이를 구분하지 않으므로 MyWidget 으로 캐스트는 성공적으로 이뤄집니다. 

    QLabel *label = qobject_cast<QLabel *>(obj);
    // label is 0

The cast to QLabel, on the other hand, fails. The pointer is then set to 0. This makes it possible to handle objects of different types differently at run-time, based on the type:

반면에 QLabel 로의 캐스팅은 실패합니다. 그러면 포인터는 0 으로 할당됩니다. 이를 이용하여 실행-중에 자료형에 따라 다르게 객체를 다루는 것이 가능하게 합니다

    if (QLabel *label = qobject_cast<QLabel *>(obj)) {
        label->setText(tr("Ping"));
    } else if (QPushButton *button = qobject_cast<QPushButton *>(obj)) {
        button->setText(tr("Pong!"));
    }

While it is possible to use QObject as a base class without the Q_OBJECT macro and without meta-object code, neither signals and slots nor the other features described here will be available if the Q_OBJECT macro is not used. From the meta-object system's point of view, a QObject subclass without meta code is equivalent to its closest ancestor with meta-object code. This means for example, that QMetaObject::className() will not return the actual name of your class, but the class name of this ancestor.

Q_OBJECT 와 메타-오브젝트 코드를 쓰지 않는 부모 클래스로 QObject 를 쓸수는 있지만, Q_OBJECT 매크로를 사용하지 않으면 시그널과 슬롯을 포함한 여기서 설명한 기능들을 사용할 수가 없습니다. 메타-오브젝트 시스템의 시점에서 메타 코드 없는 QObject 자식 클래스는 메타-코드를 사용를 사용하는 근접한 조상(부모) 클래스와 동일합니다. 예를 들어 의미를 설명하면, QMetaObject::className() 은 당신의 실제 클래스 이름을 반환하지 않고, 그 조상 클래스의 이름을 반환할 것입니다.

Therefore, we strongly recommend that all subclasses of QObject use the Q_OBJECT macro regardless of whether or not they actually use signals, slots, and properties.

그렇기 때문에, 우리는 시그널과 슬롯 그리고 속성 값들을 사용하던지 안하던지 간에 QObject 의 자식 클래스를 사용하는데 Q_OBJECT 를 매크로를 사용하는 것을 강력히 권장합니다.

See also QMetaObjectQt's Property System, and Signals and Slots.

같이 읽기 : QMetaObjectQt's Property System, 과 Signals and Slots.

© 2015 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.