用C++實現屬性

來源:互聯網
上載者:User
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的所見即所得 (WYSIWYG)編輯很有用,可以很直觀的設定某個屬性,如大小,顏色等;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<<v<<endl;
    test.ValueW = 1.0f;
    test.ValueRW
= true;
    cout<<test.ValueRW<<endl;

    return 0;
}

基本上可以滿足要求了,內部類沒有成員,一個類只佔一個位元組,比之前面的要節省得多。儘管用標準文法可以實現“屬性”,但仍有一些不足之處,首先是屬性若傳入有可變參數的函數時會有問題,如下面:
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[]

有了編譯器的支援,事情的確簡單得多了。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.