一般来说对于标准C++而言是不存在成员属性这个概念的,以前大家都是用GetXXX/SetXXX来访问或取得数据,好象也没有感觉到任何不便。但是当我们用过C#之类的语言之后,我们总觉得C++这个方式太老土了。于是我们想 ...
一 般来说对于标准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下有用。
在实现之前,我必需先探讨一下为什么需要“属性”这个东东。比如说下面雇员这个类:
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下有用。
本文转自 xkdcc 51CTO博客,原文链接:http://blog.51cto.com/brantc/168829,如需转载请自行联系原作者