一般來說對於標準C++而言是不存在成員屬性這個概念的,以前大家都是用GetXXX/SetXXX來訪問或取得資料,好象也沒有感覺到任何不便。但是當我們用過C#之類的語言之後,我們總覺得C++這個方式太老土了。於是我們想去實現“屬性”這個C++語言缺乏的要素。事實上網路上有很多人已經做了這部分工作,實現的方法有很多種,一種是用模板,一種是根據特定語言來寫的,如VC(指的是Microsoft實現的C++)。但是它們要麼很複雜,要麼很難記住它的準確用法,嗯我總是喜歡簡單的東西,因為太複雜的東東會讓我的頭腦當機。廢話少說,來看看如何?。
在實現之前,我必需先探討一下為什麼需要“屬性”這個東東。比如說下面僱員這個類:
class CEmployee
{
public:
int Old; //年齡
};
CEmployee employee;
employee.Old=22;
int old =employee.Old;
它有一個成員變數,我們可以直接對它們進行賦值或者讀取,但是往往會缺少一個很重要的東東,就是不能對所賦值進行校正,這可是個大問題,比如我們給 Old一個負值,比如-50,提示程式運行時不會有任何錯誤,但是的確這個成員變數的值在邏輯上是不正確的。於是我們會寫上GetOld、SetOld。現在OK了,這個小問題解決了,但新問題來了。我們的類使用者,他們需要重新把他們的代碼成寫如下的樣子,而不是上面的那樣。
CEmployee employee;
employee.SetOld(22);
int old =employee.GetOld();
你的夥伴一定會在寫代碼時詛咒你寫了一個垃圾的類。所以你決定要改變這個現狀。很幸運,你是MS的忠實使用者,而且你對於MSDN看很仔細,所以你知道可以這樣來寫
class CEmployee
{
private:
int m_old;
public:
_declspec(property(get= GetOld,put=SetOld))int Old;
int GetOld(void)
{
return m_old;
}
void SetOld(int value)
{
if( (value >0) && (value <60))
{
m_old = value;
}
else
{
m_old =20;
}
}
};
Very Good,上面的類完美地完成一個屬性所要做的目標,不過還有一點小問題,象我這樣比較笨的經常需要尋找MSDN才會知道
_declspec(property(get= GetOld,put=SetOld))int Old;
這句話的含義,而且我也經常忘記它的具體寫法,比如put我常把它寫成了set,這總是讓我想起了使用C#的美好時光,它是可以寫成這個樣子的
public class CEmployee
{
private int m_old;
public int Old
{
get
{ return m_old; }
set
{
if(value >0 && value <60)
{
m_old = value;
}
else
{
m_old =20;
}
}
}
}
所以我想到可以利用C/C++中強大的武器宏,我們來定義幾個宏
#define PROP(T,X) __declspec(property(get= __get##X,put= __put##X))T X;
#define GETPROP(T,X) __declspec(property(get= __get##X))T X; //唯讀屬性
#define SETPROP(T,X) __declspec(property(put= __put##X))T X; //唯寫屬必
#define GET(T,X) T __get##X(void)
#define SET(T,X) void __put##X(T value)
說明一下:T 代表屬性的類型如int,double,CString,而X代表屬性名稱。如果你需要一個唯讀屬性可以使用GETPROP,唯寫屬性則可以使用 SETPORP,然後對應使用一個GET或SET,當然如果你用PROP,而只用了一個GET或SET,也沒有錯,只是在編譯時間會告訴你沒有一個 __getXXX或__putXXX的方法。然後我們就可以這樣來寫我們的類。
class CEmployee
{
private:
int m_old;
public:
PROP(int ,Old)
GET(int,Old)
{
return m_old;
}
SET(int,Old)
{
if( (value >0) && (value <60)) //這裡的value你可把它和C#一樣當做關鍵字
{
m_old = value;
}
else
{
m_old =20;
}
}
};
好了,我們要做的工作已經做完了。當然這種方法還是有很多問題,比如不能使用C#中常用的索引屬性,靜態屬性等等。但是畢竟我們是C++程式員麼,呵呵!最後,這種方法只是在VC下有用。