1> 什么是元对象系统
    由于C++的RTTI机制只能提供有限的类型信息,于是Qt构建了自己的元对象系统(Meta-Object)。
    使用该系统的基类 QObject 所创建的派生类对象,可以在运行期获取该对象的类名、父类名、枚举类型以及有哪些成员函数等信息,基于这些信息, Qt 能够提供信号与槽的机制。

    2> 引出旧版本 c++RTTI 的局限性
    由于C++是静态类型语言,有关类的信息只在编译期被使用,编译后就不再保留,因此程序运行时无法获取类的信息。这时就需要使用「运行期类型信息」,即RTTI(Run-Time Type Information)
    例如 c++ 标准定义了 dynamic_cast ,能够将指向基类的对象指针安全地向下转化为指向派生类的指针;

    但是 RTTI 本身是有局限性的,完整地描述一个类型需要很多信息,例如类的名字、有哪些父类、有哪些成员变量、有哪些成员函数、哪些是public的、哪些是private的、哪些是protected的等等。仅靠 dynamic_cast 提供的类型信息是十分有限的。

    所以为了解决这些问题,Qt提供元对象系统机制来实现动态获取类型信息。

    3> 与 RTTI 相比 Qt 中的元对象系统的强大性
    即使编译器不支持 RTTI,通过Qt元对象系统也能动态获取类型信息;例如在任何时候调用 QMetaObject::className() 函数都会返回类的名称。

    然后相比较于 dynamic_cast(),使用 qobject_cast() 进行强制转换也会更安全,而且速度更快。

    1. QObject *obj = new QWidget();
    2. QWidget *widget = qobject_cast<QWidget *>(obj);

    4> 使用 Qt 中的元对象系统的前提条件
    Qt 中的元对象系统提供了对象间通信的信号和槽机制、运行时类型信息和动态属性系统。
    首先要使用元对象系统,需基于三个条件:

    • 该类必须继承自 QObject 类;
    • 必须在类的私有声明区声明 Q_OBJECT 宏
    • 元对象编译器 Meat-Object Compiler(moc) 为 QObject 的子类实现元对象特性提供必要的代码。

    moc 工具会读取一个 c++ 源文件,如果它发现一个或者多个类的声明中包含 QObject宏,则会新建一个 c++ 源文件(以 moc_* 打头的),其中就包含为每一个类生成的元对象代码、

    参考:https://zhuanlan.zhihu.com/p/61303678