Qt 是否可以使用“发送”从派生对象的基类发出信号;这";

Qt 是否可以使用“发送”从派生对象的基类发出信号;这";,qt,inheritance,signals-slots,Qt,Inheritance,Signals Slots,我不太清楚如何表述我的问题,我希望这更清楚。我想要一个基类,看起来像这样: class Base : public QObject { Q_OBJECT void doSomething() { emit test(this); } virtual void doSomethingElse() = 0; signals: void test(Base*); } 然后在派生类中执行以下操作: class Derived : public Base {

我不太清楚如何表述我的问题,我希望这更清楚。我想要一个基类,看起来像这样:

class Base : public QObject { 
    Q_OBJECT


    void doSomething() { emit test(this); }

    virtual void doSomethingElse() = 0;

signals:
     void test(Base*);
}
然后在派生类中执行以下操作:

 class Derived : public Base {

     void doSomethingElse() { emit test(this); }

 }

如果我现在听这个对象的信号,我听的是test(派生*)还是/和test(基本*)?

你不应该把发送者作为信号的参数。只需使用
QObject::sender()
即可获取发送信号的
QObject

例如:

然后在插槽中:

void Listener::someObject_test() {
    QObject* sender = QObject::sender();
    // or:
    Derived* sender = (Derived*)QObject::sender();
}

moc在编译时根据您在使用
Q_对象的类中声明插槽和信号的方式生成插槽和信号的列表。

此列表是字符串列表,因此如果声明:

signals:
     void test(Base*);
列表中的项目是字符串
“test(Base*)”
(您可以在输出目录中文件
moc\u YourClass.cpp
的变量
qt\u meta\u YourClass
中看到该列表)。
SIGNAL
SLOT
也返回字符串,
connect()
将其规范化,使其格式与moc生成列表中的格式相同,并将其与该列表中的字符串进行比较


派生类时,字符串没有更改,因此您仍然必须使用
信号(test(Base*))
由于派生类没有自己的信号,您将侦听测试(Base*)。

我以为文档是针对发送方的()?我使用了多次,从未遇到任何问题。文档声明“此函数违反了面向对象的模块化原则”。如果您提供对象作为信号的参数,它也将违反相同的原则。有时需要知道信号来自何处,在这种情况下,使用
QObject::sender()
是最简单的方法。
sender()
不是免费的,它锁定互斥锁并执行列表查找。如果将对象作为信号的参数传递,从语义上讲,它表明该对象是消息的一部分,您不必使用强制转换来使用对象,并且当信号和插槽属于不同的线程时,它也会工作,而不像
发送方()
。作为奖励,您甚至可以使用非发送方的对象作为参数发出信号。@alexidm,谢天谢地,Qt并不是围绕着每个信号作为参数发送发送方的概念设计的。否则,每次重写Qt类时,我都必须重写(并复制)每个发送信号的方法。此外,您必须始终强制转换从
QObject::sender()
获得的对象,因为它将始终为您提供一个
QObject
(除非您需要一个QObject,这是很少见的)。最后,我不相信列表查找会那么慢。您主要需要用户生成的事件的信号,这些事件并不那么频繁。对于任何更频繁的操作,可能会有一些优化。也许发送发送方作为参数是一种优化,也许有更好的方法。。。但无论如何,这是一个临界情况,取决于应用程序。你能具体说明“侦听”的意思吗?在这种情况下,很多事情都取决于它,例如侦听-将发送方作为插槽或?通过“connect(objectInMyExample,SIGNAL(test(Base*/Derived*))”、someOtherObject、SLOT(handleObject(Base*/Derived*))来连接它,这样在handleObject(Base*)中它将处理Base和handleObject(Derived*))它会侦听派生的。我应该使信号虚拟化还是更好地从BaseCase-派生类中抛出而不是使用发送器和从QOBject到基类/派生类的转换?技术上是的,即使MOC会给您警告。并且C++不支持协变或逆变参数,所以<代码>测试(BASE *)
测试(派生*)
将是不相关的。您仍然可以通过执行依赖于对象本身的
Base*
派生*
的部分来避免强制转换,方法是通过虚拟函数或使用访问者模式。hm。因此,如果我的理解正确,如果我在基类中的函数是虚拟的,那么我是否获得指向基*,我仍然会得到虚拟函数等。
signals:
     void test(Base*);