<var id="fnfpo"><source id="fnfpo"></source></var>
<rp id="fnfpo"></rp>

<em id="fnfpo"><object id="fnfpo"><input id="fnfpo"></input></object></em>
<em id="fnfpo"><acronym id="fnfpo"></acronym></em>
  • <th id="fnfpo"><track id="fnfpo"></track></th>
  • <progress id="fnfpo"><track id="fnfpo"></track></progress>
  • <tbody id="fnfpo"><pre id="fnfpo"></pre></tbody>

  • x
    x

    用C++實現屬性

    發布時間:2011-3-29 20:18    發布者:1770309616
    關鍵詞: 屬性
    Delphi和C#的類都提供了“屬性”的概念,使得Getter和Setter的方法可以像訪問成員一樣簡單,如下面的Delphi代碼:
    TMyClass = class
    private
        FValue: Integer;
        funcation GetValue: Integer;
        procedure SetValue(value: Integer);
    public
        property Value: Integer read GetValue write SetValue;
    end;
    紅色部分就是屬性的聲明,以后可以直接對Value進行讀寫,像下面這樣:
    MyClass.Value := 100;
    v = MyClass.Value;
    屬性有幾個顯而易見的好處:
    •與Getter和Setter相比更加簡單,就像直接訪問成員一樣。
    •與直接訪問成員相比,屬性可以控制讀寫權限,并通過Getter和Setter對代碼進行檢驗。
    •屬性對UI的所見即所得編輯很有用,可以很直觀的設置某個屬性,如大小,顏色等;QT似乎也大量應用屬性,不過我沒有去看過。
    C++原生沒有支持屬性,但這個語言的特點就是語法強大,通過一些高級屬性就可以實現其他語言的特性。要實現屬性,C++當然是可以勝任了,而且實現方式有很多,我在網上就看過幾種實現。不過在這里我要講另外兩種實現,一種是我想到的,另一種是編譯器的擴展。

    先看第一種,網上通常的實現是用“模板+操作符重載”的方式,這種方式需要在類的構造函數中初始化模板類成員,并且模板類包含了3個成員:外部類指針和讀寫函數指針。這個模板類成員就是“屬性”,一個屬性將浪費掉一些存儲,如果一個類存在大量屬性,則這個類的空間尺寸是可觀的。

    我的實現是用“本地類+操作符重載”的方式,用了3種本地類,分別實現“只讀,只寫,可讀寫”三種屬性,用宏包裝起來方便使用,請看下面的代碼:
    // 取外部類實例指針(this)
    // outClass 外部類名
    // localClassMem 本地類成員
    #define OUTCLASS_THIS(outClass, localClassMem) ((outClass*)((unsigned char*)this - offsetof(outClass, localClassMem)))
    // 屬性定義宏
    // cls 定義屬性的類
    // type 屬性的類型
    // propname 屬性名
    // getter 讀函數
    // setter 寫函數
    #define PROPERTY_R(cls, type, propname, getter) \
        class property_##getter \
        { \
        public: \
            operator type () \
            { \
                return OUTCLASS_THIS(cls, propname)->getter(); \
            } \
        } propname
    #define PROPERTY_W(cls, type, propname, setter) \
        class property_##setter \
        { \
        public: \
            property_##setter &operator = (const type& value) \
            { \
                OUTCLASS_THIS(cls, propname)->setter(value); \
                return *this; \
            } \
        } propname  
    #define PROPERTY_RW(cls, type, propname, getter, setter) \
        class property_##getter_##setter \
        { \
        public: \
            operator type () \
            { \
                return OUTCLASS_THIS(cls, propname)->getter(); \
            } \
            property_##getter_##setter &operator = (const type& value) \
            { \
                OUTCLASS_THIS(cls, propname)->setter(value); \
                return *this; \
            } \
        } propname
    有了這幾個宏,就可以寫一個測試類來看看結果了:
    class Test
    {
    public:
        PROPERTY_R(Test, int, ValueR, GetValueR);
        PROPERTY_W(Test, float, ValueW, SetValueW);
        PROPERTY_RW(Test, bool, ValueRW, GetValueRW, SetValueRW);    Test(): mValueR(100), mValueW(0), mValueRW(false)
        {
        }
        int GetValueR()
        {
            return mValueR;
        }
        void SetValueW(const float value)
        {
            mValueW = value;
        }
        bool GetValueRW()
        {
            return mValueRW;
        }
        void SetValueRW(bool value)
        {
            mValueRW = value;
        }
    private:
        int mValueR;
        float mValueW;
        bool mValueRW;
    };int _tmain(int argc, _TCHAR* argv[])
    {
        Test test;
        int v = test.ValueR;
        cout<     test.ValueW = 1.0f;
        test.ValueRW = true;
        cout< }
    基本上可以滿足要求了,內部類沒有成員,一個類只占一個字節,比之前面的要節省得多。
    盡管用標準語法可以實現“屬性”,但仍有一些不足之處,首先是屬性若傳入有可變參數的函數時會有問題,如下面:
    printf("%d", test.ValueR);
    編譯器識別不出可變參數的具體類型,因此ValueR并沒有默認轉換為int,要這樣寫才正確:
    printf("%d", (int)test.ValueR);
    另外一個問題是“數組屬性”如何實現,至少我沒有找到更好的辦法,若哪位朋友有好的辦法,不訪分享出來。

    如果你確定你的代碼只會運行在Windows上,并且只用VC作為編譯器,那么就可以用第二種實現。微軟提供了property關鍵字用來支持屬性機制,編譯器會自動將屬性替換為Get或Set函數,這樣一來屬性就根本不占用任何空間,也沒有任何調用開銷。
    下面同樣包裝了幾個宏,不僅實現了普通屬性,也實現了數組類型的屬性:
    #define PROPERTY_R(type, propname, getter) __declspec(property(get=getter)) type propname
    #define PROPERTY_W(type, propname, setter) __declspec(property(put=setter)) type propname
    #define PROPERTY_RW(type, propname, getter, setter) __declspec(property(get=getter, put=setter)) type propname
    #define PROPERTY_ARRAY_R(type, propname, getter) __declspec(property(get=getter)) type propname[]
    #define PROPERTY_ARRAY_W(type, propname, getter) __declspec(property(put=setter)) type propname[]
    #define PROPERTY_ARRAY_RW(type, propname, getter, setter) __declspec(property(get=getter, put=setter)) type propname[]
    有了編譯器的支持,事情的確簡單得多了。
    本文地址:http://www.portaltwn.com/thread-60396-1-1.html     【打印本頁】

    本站部分文章為轉載或網友發布,目的在于傳遞和分享信息,并不代表本網贊同其觀點和對其真實性負責;文章版權歸原作者及原出處所有,如涉及作品內容、版權和其它問題,我們將根據著作權人的要求,第一時間更正或刪除。
    您需要登錄后才可以發表評論 登錄 | 立即注冊

    廠商推薦

    • Microchip視頻專區
    • EtherCAT®和Microchip LAN925x從站控制器介紹培訓教程
    • MPLAB®模擬設計器——在線電源解決方案,加速設計
    • 讓您的模擬設計靈感,化為觸手可及的現實
    • 深度體驗Microchip自動輔助駕駛應用方案——2025巡展開啟報名!
    • 貿澤電子(Mouser)專區

    相關視頻

    關于我們  -  服務條款  -  使用指南  -  站點地圖  -  友情鏈接  -  聯系我們
    電子工程網 © 版權所有   京ICP備16069177號 | 京公網安備11010502021702
    快速回復 返回頂部 返回列表
    精品一区二区三区自拍图片区_国产成人亚洲精品_亚洲Va欧美va国产综合888_久久亚洲国产精品五月天婷