> Qt had an awful hack to support C++-style callbacks through the MOC preprocessor, which, in the end, were "compiled" into C-style callbacks. AFAIK, after C++11 they moved from this.
Nothing really awful about it. MOC is the MetaObject Compiler, and it's needed to support introspection. In standard C++ you can't just list the methods or properties any random thing has, for instance.
Signals are also pretty complex. At the simplest, yes, they're more or less a C callback. But they can also be queued and sent between threads, and that of course needs special support that Qt does for you behind the scenes.
What changed in newer releases is that signal syntax moved from using strings:
connect(sender, SIGNAL(destroyed(QObject*)), this, SLOT(objectDestroyed()));
// This is pretty much:
connect(sender, "destroyed(QObject*)", this, "objectDestroyed()");
to references:
connect(sender, &QObject::destroyed, this, &MyObject::objectDestroyed);
Which means connections are checked at compile time instead of at runtime, and you can also connect signals to functors or lambdas.