Посмотрите на это:
Counter a, b; // objects created on the stack, they are not pointers
// get the addresses of the objects and assign them as pointers.
Counter *aPointer = &a;
Counter *bPointer = &b;
Следующее не будет компилироваться, потому что a и b не являются указателями, а QObject connect ожидает указатели на экземпляры классов, которые наследуются от QObject.
QObject::connect(a, &Counter::valueChanged, b, &Counter::setValue);
Следующее будет скомпилировано, потому что вы предоставляете указатели:
QObject::connect(aPointer, &Counter::valueChanged, bPointer, &Counter::setValue);
Точно так же это работает, потому что вы берете адрес (он же указатель) объектов:
QObject::connect(&a, &Counter::valueChanged, &b, &Counter::setValue);
Это, мы надеемся, объясняет & перед объектами. Затем перед именами функций стоят & s . Это синтаксис указателя на функцию-член:
&Counter::valueChanged
Имя класса (Counter), к которому добавляются :: и имя функции-члена (valueChanged), с предшествующим & .
Это элемент указателя, который предоставляется в качестве первого аргумента в этом случае. Этот называется сигналом. Под капотом Qt зовет их вместе.
QObject *sender = &a;
std::function<void()> signal = std::bind(&Counter::valueChanged,sender);
...
signal(); // the function is called here
То же самое происходит со слотом.
Наконец, используются макросы SIGNAL () и SLOT ()
Надеюсь, это прояснит некоторые ваши вопросы.