Qt學習記錄--05 函數指針以及類函數指針用於Qt信號槽

一 函數指針:

        顧名思義,函數指針即指向函數之指針,它與其他普通類型指針一樣,所佔內存爲4個字節(32位系統)。所不同的是其內部存儲了函數的地址而非數據地址,函數指針可以實現對參數類型參數順序返回值都相同的函數進行封裝,是多態的一種實現方式。

        其一般的使用非常簡單,假如返回值爲int類型,入參有兩個從左到右分別爲char*和int,那麼聲明此類函數指針如下:

int (*pFunc)(char*, int);

        假設有如下形式的函數:

int Test(char *pSz, int nCount);
        那麼函數指針的使用如下:

pFunc = Test;
// 亦可
pFunc = &Test;

        說個更有趣的使用(祕密武器, 一般人不告訴他...):

//! 都可以
pFunc = *Test;
PFunc = **Test;
pFunc = ***Test;
//...
        實際使用一般會用typedef定義爲一種類型:

typedef int (*PFUNC)(char*, int);
        使用時,需先要聲明對象:

PFUNC pFunc = Test;

二 類函數指針:

        類的靜態成員函數採用與一般函數指針相同的調用方式不受this指針的影響;類的非靜態成員函數與一般函數指針是不兼容的。而且,不同類的this指針是不一樣的,因此,指向不同類的非靜態成員函數的指針也是不兼容的。指向類的非靜態成員函數的指針,在聲明時就需要添加類名

        類函數指針之靜態成員函數:

//! 指向一般類的靜態成員函數的指針定義
typedef int (*pGeneralFun)(int, int);
        類函數指針之非靜態成員函數:

//! 指向類的非靜態成員函數的指針定義
typedef int (CA::*pClassFun)(int, int);

三 類函數指針在Qt信號槽的使用:

有如下程序(照搬之):

//!!! Qt5
#include <QObject>

////////// newspaper.h
class Newspaper : public QObject
{
    Q_OBJECT
public:
    Newspaper(const QString & name) :
        m_name(name)
    {
    }

    void send() const
    {
        emit newPaper(m_name);
    }

signals:
    void newPaper(const QString &name) const;

private:
    QString m_name;
};

////////// reader.h
#include <QObject>
#include <QDebug>

class Reader : public QObject
{
    Q_OBJECT
public:
    Reader() {}

    void receiveNewspaper(const QString & name) const
    {
        qDebug() << "Receives Newspaper: " << name;
    }
};

////////// main.cpp
#include <QCoreApplication>

#include "newspaper.h"
#include "reader.h"

int main(int argc, char *argv[])
{
    QCoreApplication app(argc, argv);

    Newspaper newspaper("Newspaper A");
    Reader reader;
    QObject::connect(&newspaper, &Newspaper::newPaper,
                     &reader,    &Reader::receiveNewspaper);
    newspaper.send();

    return app.exec();
}
        上面connect()函數可以正常綁定信號槽,但是信號如同普通成員函數一樣也支持重載,添加如下信號:

void newPaper(const QString &name, const QDate &date);
        按照前面的寫法,編譯器會報出一個錯誤由於這個函數(注意,信號實際也是一個普通的函數)有重載,因此不能用一個取址操作符獲取其地址。在 Qt 4 中,我們使用SIGNAL和SLOT兩個宏來連接信號槽。如果有一個帶有兩個參數的信號,由於其信號槽的連接是帶參數的,所以connect()函數使用Qt4的風格編寫是沒有問題的,代碼如下:

QObject::connect(&newspaper, SIGNAL(newPaper(QString, QDate)),
                 &reader,    SLOT(receiveNewspaper(QString, QDate)));
        此種場景下,之前講述的類成員(非靜態)函數指針便派上用場了:

void (Newspaper:: *newPaperNameDate)(const QString &, const QDate &) = &Newspaper::newPaper;
QObject::connect(&newspaper, newPaperNameDate,
                 &reader,    &Reader::receiveNewspaper);
        根本原因是,我們指明瞭函數類型,使編譯器能夠準確定位。當然你也可以直接聲明(類型轉換):
QObject::connect(&newspaper, (void (Newspaper:: *)(const QString &, const QDate &))&Newspaper::newPaper,
                 &reader,     &Reader::receiveNewspaper);
        本文簡要講述了函數指針及其在Qt的信號槽中的使用,部分代碼取自互聯網,感謝分享。還有一些其他細節就不在此展開了,請自行查閱,見諒!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章