1. 程式人生 > >Qt訊號槽機制對傳輸引數上的侷限性

Qt訊號槽機制對傳輸引數上的侷限性

訊號與槽機制是比較靈活的,但有些侷限性我們必須瞭解,這樣在實際的使用過程中做到有的放矢,避免產生一些錯誤。下面就介紹一下這方面的情況。

1.訊號與槽的效率是非常高的,但是同真正的回撥函式比較起來,由於增加了靈活性,因此在速度上還是有所損失。
當然這種損失相對來說是比較小的,通過在一臺i586-133的機器上測試是10微秒(執行Linux),可見這種機制所提供的簡潔性、靈活性還是值得的。但如果我們要追求高效率的話,比如在實時系統中就要儘可能的少用這種機制。

2.訊號與槽機制與普通函式的呼叫一樣,如果使用不當的話,在程式執行時也有可能產生死迴圈。
因此,在定義槽函式時一定要注意避免間接形成無限迴圈,即在槽中再次發射所接收到的同樣訊號。例如,在前面給出的例子中如果在mySlot()槽函式中加上語句emit mySignal()即可形成死迴圈。

3.如果一個訊號與多個槽相聯絡的話,那麼,當這個訊號被髮射時,與之相關的槽被啟用的順序將是隨機的。

  1. 巨集定義不能用在signal和slot的引數中。
    既然moc工具不擴充套件#define,因此,在signals和slots中攜帶引數的巨集就不能正確地工作,如果不帶引數是可以的。例如,下面的例子中將帶有引數的巨集SIGNEDNESS(a)作為訊號的引數是不合語法的:
    #ifdef ultrix
    #define SIGNEDNESS(a) unsigned a
    #else
    #define SIGNEDNESS(a) a
    #endif
    class Whatever : public QObject
    {
    […]
    signals:
    void someSignal( SIGNEDNESS(a) );
    […]
    };

  2. 建構函式不能用在signals或者slots宣告區域內。
    的確,將一個建構函式放在signals或者slots區內有點不可理解,無論如何,不能將它們放在private slots、protected slots或者public slots區內。下面的用法是不合語法要求的:
    class SomeClass : public QObject
    {
    Q_OBJECT
    public slots:
    SomeClass( QObject *parent, const char *name )
    : QObject( parent, name ) {} // 在槽宣告區內宣告建構函式不合語法
    […]
    };

  3. 函式指標不能作為訊號或槽的引數。
    例如,下面的例子中將void (applyFunction)(QList, void*)作為引數是不合語法的:
    class someClass : public QObject
    {
    Q_OBJECT
    […]
    public slots:
    void apply(void (applyFunction)(QList, void*), char*); // 不合語法
    };

你可以採用下面的方法繞過這個限制:
typedef void (ApplyFunctionType)(QList, void*);
class someClass : public QObject
{
Q_OBJECT
[…]
public slots:
void apply( ApplyFunctionType, char *);
};
7.訊號與槽不能有預設引數。
既然signal->slot繫結是發生在執行時刻,那麼,從概念上講使用預設引數是困難的。
下面的用法是不合理的:
class SomeClass : public QObject
{
Q_OBJECT
public slots:
void someSlot(int x=100); // 將x的預設值定義成100,在槽函式宣告中使用是錯誤的
};
8.訊號與槽也不能攜帶模板類引數。
如果將訊號、槽宣告為模板類引數的話,即使moc工具不報告錯誤,也不可能得到預期的結果。 例如,下面的例子中當訊號發射時,槽函式不會被正確呼叫:
[…]
public slots:
void MyWidget::setLocation (pair<int,int> location);
[…]
public signals:
void MyObject::moved (pair<int,int> location);
但是,你可以使用typedef語句來繞過這個限制。如下所示:

typedef pair<int,int> IntPair;
[…]
public slots:
void MyWidget::setLocation (IntPair location);
[…]
public signals:
void MyObject::moved (IntPair location);
這樣使用的話,你就可以得到正確的結果

還有一種方法:使用 qRegisterMetaType<QVector >(“QVector”);這樣就可以使用QVector作為引數型別了

9.巢狀的類不能位於訊號或槽區域內,也不能有訊號或者槽。
例如,下面的例子中,在class B中宣告槽b()是不合語法的,在訊號區內宣告槽b()也是不合語法的。
class A
{
Q_OBJECT
public:
class B
{
public slots: // 在巢狀類中宣告槽不合語法
void b();
[…]
};
signals:
class B
{
// 在訊號區內宣告巢狀類不合語法
void b();
[…]
}:
};

10.友元宣告不能位於訊號或者槽宣告區內。

相反,它們應該在普通C++的private、protected或者public區內進行宣告。下面的例子是不合語法規範的:

class someClass : public QObject
{
    Q_OBJECT
[...]
signals: //訊號定義區
    friend class ClassTemplate; // 此處定義不合語法
};

原文:https://blog.csdn.net/hustyangju/article/details/22275735?utm_source=copy