• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            隨筆 - 30  文章 - 67  trackbacks - 0
            <2013年7月>
            30123456
            78910111213
            14151617181920
            21222324252627
            28293031123
            45678910

            常用鏈接

            留言簿(8)

            隨筆分類

            隨筆檔案

            文章檔案

            收藏夾

            Oops

            搜索

            •  

            積分與排名

            • 積分 - 85466
            • 排名 - 276

            最新評論

            閱讀排行榜

            評論排行榜

            簡介

            本文主要講解Qt是如何實現反射,以及一點點反射使用的小心得。

            文章概覽

            Qt反射內幕小窺

            詳細內容

            反射前期準備

            得到注冊的類成員變量

            得到注冊的類成員函數

            訪問類成員屬性(get,set)

            調用注冊的函數

            反射應用

            總結

            Qt反射內幕小窺

            Qt反射機制是基于moc(meta object compiler)實現的,在這里多插一句(可以說Qt所有C++沒有的特性,幾乎都和這個有關系)。但是需要注意的是Qt提供的反射式基本的反射,不支持類的反射,這個與Java,C#還是有差別的。

            moc講解

            通常C++的編譯過程為

            預處理->編譯->鏈接->運行

            Qt編譯的過程中,有一個moc的過程,在Qt工程構建過程中的qmake其實就是干這個事的。moc->預處理->編譯->鏈接->運行。

            在moc過程中,需要處理的事情如下:

            1、 識別一些特殊的宏Q_OBJECT、Q_PROPERTY、Q_INVOKABLE。。。; 如果碰到這些關鍵字,Qt自然就會去生成對應的moc文件。

            2、 slot,signal自然也是如此。

            3、 uidesigner,同樣也是在這個階段處理的;

            詳細內容

             

            反射前期準備

            1、 首先得繼承于Q_Object,同時需要在class中加入Q_OBJECT,但是Q_Object的構造函數默認是私有的不讓繼承。

            在類中直接使用Q_GADGET也可以實現反射,。。。據說只能實現部分功能,目前我只實現到能遍歷成員屬性,函數,但是不能訪問其中的值。

            這個過程其實就是定義QMetaObject的過程,具體見Qt源碼

            2、 注冊類成員變量需要使用Q_PROPERTY

            Q_PROPERTY( type member READ get WRITE set) 其中READ,WRITE是關鍵字

            Type表示成員的類型(不支持自定義類型,對Qt很多基本類型都支持);

            Member代表你給該成員另外起的名字,可以和變量名不同;get,set就是自己在C++函數里面定義的基本的訪問函數名,不需要寫參數。直接上代碼:

            3、 注冊類成員函數

            如果你希望這個函數能夠被反射,那么很簡單,只需要在類的函數聲明前加入Q_INVOKABLE關鍵字。

            例如Q_INVOKABLE int func( QString flag );

               #include <QObject>
               class MyClass : public QObject
               {
                Q_OBJECT
                Q_PROPERTY(int Member1 READ Member1 WRITE setMember1 )
                Q_PROPERTY(int Member2 READ Member2 WRITE setMember2 )
                Q_PROPERTY(QString MEMBER3 READ Member3 WRITE setMember3 )
               public:
                explicit MyClass(QObject *parent = 0);
               signals:
               public slots:
               public:
                Q_INVOKABLE int Member1();
                Q_INVOKABLE int Member2();
                Q_INVOKABLE QString Member3();
                Q_INVOKABLE void setMember1( int mem1 );
                Q_INVOKABLE void setMember2( int mem2 );
                Q_INVOKABLE void setMember3( const QString& mem3 );
                Q_INVOKABLE int func( QString flag );
               private:
                int m_member1;
                int m_member2;
                QString m_member3;
               };

            得到注冊的類成員變量

              MyClass theObj;
             const QMetaObject* metaObj = theObj.metaObject();
             //1.遍歷類的屬性
             int propertyCnt = metaObj->propertyCount();
             for ( int i = 0; i < propertyCnt; ++ i )
             {
             QMetaProperty oneProperty = metaObj->property( i );
             cout << " name: " << oneProperty.name();
             cout << " type: " << QVariant::typeToName( oneProperty.type()) << "\n";
              }

            主要思路就是得到其元對象,得到其元屬性,然后就能得到你需要的信息,具體的訪問函數有name,type,需要注意的是得到的type是枚舉值,還在Qt提供了typeToName的函數,你可以得到想要的(例如不是空洞的2,而是”int”)。

            得到注冊的類成員函數

            //2.遍歷類的函數成員
             int methodCnt = metaObj->methodCount();
             for ( int idx = 0; idx < methodCnt; ++ idx )
             {
             QMetaMethod oneMethod = metaObj->method( idx );
             cout << "--------begin-------" << "\n";
             cout << " typeName: " << oneMethod.typeName() << "\n";
             cout << " signature: " << oneMethod.signature() << "\n";
             cout << " methodType: " << oneMethod.methodType() << "\n";
             cout << "--------end---------" << "\n";
              }

            和遍歷類屬性一致,其實就是根據元對象,得到元函數;

            其中typeName代表返回類型,signature只的是函數的原貌,methodType代表函數的類型,在Qt中分為三類(槽,信號,普通函數)。

            訪問類成員屬性(get,set)

            //3.使用反射
             cout << "-------test property-----------" << "\n";
             MyClass newObj;
             newObj.setProperty("Member1", 66);
             cout << newObj.property( "Member1" ).toString().toStdString() << "\n";
             cout << newObj.Member1() << "\n";
             cout << "--------end----------" << "\n";

            在這里使用的是QObject的property() 和setProperty方法,來訪問成員信息。但是對于使用Q_GADGET宏的類,是不能使用這個方法的,還在尋找解決方法,基本思路當然是重寫。

            調用注冊的函數

              int ret;
              MyClass newObj;
             newObj.setMember1( 20 );
             newObj.setMember2( 50 );
             QMetaObject::invokeMethod( &newObj, "func", Qt::DirectConnection,
             Q_RETURN_ARG(int, ret ),
             Q_ARG(QString, "+"));

            //普通函數的調用

            在MyClass中,我們定義了int func( QString flag );這個函數,利用反射的調用方式如上,主要是理解invokeMethod的用法,其中Qt::DirectConnection是函數的執行方式,分為(異步和同步),Q_RETURN_ARG是返回參數,Q_ARG是傳入參數,需要按函數聲明中參數的順序依次傳入,Qt最多支持9個參數,對于一般的應用沒有問題。還有疑問,請移步具見Qt強大的幫助文檔。

            反射的應用

            反射反射,就我目前的認知水平來看,通過使用字符串,來實現函數的通用化調用,例如你可以利用反射把很多函數放置到數組中,實現一次遍歷,全部調用。

            目前我見到的大多是利用反射來操作數據庫,例如hibernate,其實可以利用Qt的反射,快速實現所謂的hibernate,(最近自己獨立實現了一套,很方便)。

            總結

            這篇文章主要講了如何使用Qt來實現反射,在實用角度上來講,我們不需要了解Qt是怎么實現反射的,對于怎么用上面說的很清楚了。大家有什么的新的想法,希望能提出來,來電請咨詢
            <levard@gmail.com>

            posted on 2013-07-13 22:19 Cunch 閱讀(14395) 評論(1)  編輯 收藏 引用 所屬分類: C++Qt

            FeedBack:
            # re: Qt反射 2013-07-17 17:01 tb
            發射總結不出  回復  更多評論
              
            久久久WWW成人免费精品| 思思久久精品在热线热| 亚洲综合精品香蕉久久网97 | 久久国产精品成人免费| 99久久精品无码一区二区毛片| 国产A级毛片久久久精品毛片| 亚洲欧洲精品成人久久曰影片 | 亚洲AV成人无码久久精品老人| 国产精品青草久久久久婷婷| 伊人精品久久久久7777| 精品久久久噜噜噜久久久 | 久久久www免费人成精品| 久久精品国产91久久麻豆自制 | 亚洲精品午夜国产VA久久成人| 久久精品国产亚洲欧美| 亚洲综合熟女久久久30p| 久久99热这里只有精品国产| 精品久久久久久中文字幕人妻最新| 久久久久久久综合日本| 国产精品欧美亚洲韩国日本久久| 潮喷大喷水系列无码久久精品| 久久夜色精品国产噜噜亚洲a| 精品久久久久久无码中文字幕| 777米奇久久最新地址| 国产成人无码精品久久久性色| 青青热久久国产久精品 | 久久综合色老色| 色偷偷91久久综合噜噜噜噜| 久久99精品久久久久久秒播| 久久这里只精品国产99热| 国产精品欧美久久久天天影视| 无码专区久久综合久中文字幕| 久久婷婷五月综合色奶水99啪| 久久九色综合九色99伊人| 久久精品国产色蜜蜜麻豆| 久久精品女人天堂AV麻| 美女写真久久影院| 久久精品无码一区二区app| 久久久亚洲精品蜜桃臀| 精品国产日韩久久亚洲| 久久久久亚洲精品无码蜜桃|