槽函数必须继承qobject、声明q_object宏并置于slots区,才能被信号触发;普通函数无元对象注册,无法响应信号,仅可手动调用,且不支持跨线程自动投递。

你在写Qt界面时,点击按钮却没反应,或者明明写了函数却收不到信号——这八成是把普通函数当槽函数用了,又或者该用槽的地方硬套普通函数逻辑。
槽函数必须依附于QObject体系
第一步:确认你的类是否继承自QObject。不是QMainWindow、QWidget或QDialog的直接/间接子类?那它天生就不支持槽函数。
第二步:在类声明开头加上Q_OBJECT宏。漏掉这行,MOC编译器根本不会为你生成槽函数的元对象代码,所有connect都会静默失败。
第三步:把函数声明放在public slots:、private slots:或protected slots:区块下(Qt5及以上也允许直接写在public/private区域,但【必须有Q_OBJECT且类继承QObject】)。否则即使名字叫onClicked,它也只是个普通函数。
信号只能触发槽,不能触发普通函数
方法一:用QObject::connect()连接信号和槽
connect(ui->pushButton, &QPushButton::clicked, this, &MyWidget::onButtonClicked);——这里onButtonClicked必须是槽函数,否则编译报错或运行时不响应。
方法二:用旧式宏语法(已不推荐)
connect(ui->pushButton, SIGNAL(clicked()), this, SLOT(onButtonClicked()));——SLOT宏只认真正被MOC处理过的槽,普通函数名填进去会编译失败。
注意:你不能用connect()把信号连到一个普通成员函数上,Qt会直接拒绝这种绑定,连编译都过不去。
Qt Creator 18.0.2 Windows x86_64 历史版本安装包,适合需要旧版本 IDE、旧项目兼容、Qt/C++ 项目维护、构建套件配置和调试环境回退的用户使用。
调用方式完全不同
槽函数可以两种方式调用:既可以通过信号自动触发,也能像普通函数一样手动调用,比如onButtonClicked();。
普通函数只能手动调用,它对信号完全免疫,无论你发多少次clicked(),它都不会动一下。
关键区别在于:槽函数在MOC生成的元对象信息里注册了签名,普通函数没有——Qt靠这个注册信息决定“能不能被信号找到”。【没注册=看不见】
参数传递规则差异明显
① 槽函数接收信号参数时,参数数量可以少于信号参数数,多余参数会被忽略。例如信号带两个int,槽只写一个int参数,合法。
② 普通函数调用时,实参个数和类型必须严格匹配声明,少一个或多一个都会编译报错。
③ 槽函数参数不能有默认值,也不能是模板类型或函数指针;普通函数没这些限制。
④ 信号的返回类型强制为void,槽函数虽可声明返回值,但connect后实际调用时返回值总被丢弃——这点新手常误以为能拿返回值做判断,其实不行。
线程行为天然不同
槽函数支持跨线程连接模式:用Qt::QueuedConnection时,信号发在子线程,槽会在主线程事件循环中执行;普通函数调用永远发生在当前线程,想跨线程就得自己加锁、发事件、走队列——全得手写。
一个按钮点击信号连到槽,哪怕槽在另一个线程的对象里,Qt自动帮你投递;连到普通函数?直接崩溃或数据竞争,因为没做任何线程保护。










