c++ 属性(转)
c++ 属性
 ,只能用c++进行扩展汗死死死
,只能用c++进行扩展汗死死死
“__declspec”是Microsoft c++中专用的关键字,它配合着一些属性可以对标准C++进行扩充。这些属性有:
align、allocate、deprecated、dllexport、dllimport、 naked、noinline、noreturn、nothrow、novtable、selectany、thread、property和uuid。

template <class T1, class T2> class KeyValuePair
{
private:
//-- 参数
T1 *Key;
//------值
T2 *Value;
public
:
KeyValuePair()
{
Key=new T1;
Value=new T2;
}
~KeyValuePair()
{
delete Key;
delete Value;
}
public :
T1 GetKey()
{
return this->Key;
}
T1 SetKey(T1 inputKey)
{
this->Key=inputKey;
}
private :
int m_old;
public:
//---------属性----get--------set--------返回数据---属性名称
_declspec(property(get=GetOld,put=SetOld))int Old;
int GetOld(void)
{
return m_old;
}
void SetOld(int value)
{
m_old=value;
}
};
{
KeyValuePair<int,int> c1;
c1.Old=123;
cout<<c1.Old;
}
给C++添加属性机制
来源:http://blog.csdn.net/pankun/archive/2006/02/08/594274.aspx
    以前用DELPHI和C#时,对DELPHI和C#语法中的属性感到十分方便,在读写属性时能自动调用属性的get, set函数或代码.但我最喜欢的C++中没有属性机制.不过C++提供了范型编程和操作符重载机制,足以让一切变成可能.
    假定要添加属性的类是目标类,给C++添加属性机制,我的想法是建立一个类,重载此类的 "=" 操作符,这样给这个类赋值时,会调用此类的operator = 函数,在此函数中调用目标类的类成员函数即可.但要调用目标类的类成员函数,需要目标类类指针和类成员函数指针.类成员函数指针的类型可以通过模板传入.废话不多说,代码如下:(VC7中编译通过,GCC还未测试)
Property.h
    /* 
  by 剑神一笑
  属性定义单元
*/
#ifndef PROPERTY_H
#define PROPERTY_H
//辅助类,用来定义类成员函数指针类型
template<typename T, typename U>
class PropertyType
{
public:
    //指向类成员函数的指针类型
    typedef void (U::*SetProc)(const T&);
    typedef const T& (U::*GetProc)();        
};
//属性基类
template<typename U>
class PropertyBase
{
protected:
    //拥有这个属性的类的指针
    U* obj_;
public:
    void SetObj(U *obj) 
    {
        this->obj_ = obj;
    }
};
//只写属性过程定义
template<typename T, typename U, typename PropertyType<T, U>::SetProc Set>
class WriteProperty: public PropertyBase<U>
{
protected:
    //定义属性set的函数指针
    typename PropertyType<T, U>::SetProc SetValue;
public:
    WriteProperty()
    {
        this->SetValue = Set;
    }
    void operator= (const T &value) const
    {
        (obj_->*SetValue)(value);
    }
};
//只读属性过程定义
template<typename T, typename U, typename PropertyType<T, U>::GetProc Get>
class ReadProperty: public PropertyBase<U>
{
private:
    //避免让只读属性可写
    void operator= (const T&) {}
    void operator= (const ReadProperty<T, U, Get>&) {}
protected:
    //定义属性get的函数指针
    typename PropertyType<T, U>::GetProc GetValue;
public:
    ReadProperty()
    {
        this->GetValue = Get;
    }
    operator T() const
    {
        return (obj_->*GetValue)();
    }
};
template<typename T, typename U, typename PropertyType<T, U>::GetProc Get>
std::ostream& operator << (std::ostream &out, const ReadProperty<T, U, Get>& rv) 
{
    out << rv.operator T();
    return out;
}
//读写属性过程定义
template<typename T, typename U, typename PropertyType<T, U>::SetProc Set, typename PropertyType<T, U>::GetProc Get>
class ReadWriteProperty: public PropertyBase<U>
{
private:
    typename PropertyType<T, U>::SetProc SetValue;
    typename PropertyType<T, U>::GetProc GetValue;
    //禁用赋值和拷贝构造
    const ReadWriteProperty<T, U, Set, Get>& operator= (const ReadWriteProperty<T, U, Set, Get>&) {}
    ReadWriteProperty(ReadWriteProperty<T, U, Set, Get>&) {}
public:
    ReadWriteProperty()
    {
        SetValue = Set;
        GetValue = Get;
    }
    const ReadWriteProperty<T, U, Set, Get>& operator= (const T &value) const
    {
        (obj_->*SetValue)(value);
        return *this;
    }
    operator T() const
    {
        return (obj_->*GetValue)();
    }
};
template<typename T, typename U, typename PropertyType<T, U>::SetProc Set, typename PropertyType<T, U>::GetProc Get>
std::ostream& operator << (std::ostream &out, const ReadWriteProperty<T, U, Set, Get>& rv) 
{
    out << rv.operator T();
    return out;
}
//简化函性定义的宏
//定义读写属性
#define PROPERTY_DECLARE_RW(property_name, type, class_type, set, get) \
    ReadWriteProperty<type, class_type, class_type::set, class_type::get> property_name;
//定义只读属性
#define PROPERTY_DECLARE_R(property_name, type, class_type, get) \
    ReadProperty<type, class_type, class_type::get> property_name;
//定义只写属性
#define PROPERTY_DECLARE_W(property_name, type, class_type, set) \
    WriteProperty<type, class_type, class_type::set> property_name;
#define INIT_PROPERTY(property_name) property_name.SetObj(this);
#endif//PROPERTY_H
//-------------------------华丽的分隔线-----------------------------
测试代码
#include <iostream>
#include <string>
#include "Property.h"
using std::cin;
using std::cout;
using std::string;
class Test
{
private:
    int value_;
    string name_;
public:
    Test(int value) 
    {
        INIT_PROPERTY(Value);
        INIT_PROPERTY(Name);
        INIT_PROPERTY(WValue);
        this->value_ = value;
        name_ = "TestClass";
    }
    void SetValue(const int& value) 
    {
        cout << "Set Value: " << value << std::endl;
        this->value_ = value;
    }
    const int& GetValue() 
    {
        cout << "Get Value: " << value_ << std::endl;
        return value_;
    }
    const string& GetName() 
    {
        return name_;
    }
    void ShowValue()
    {
        cout << "Value: " << value_ << std::endl;
    }
    //声明可读写属性,参数为: 属性名,属性类型,当前类名,Set函数,Get函数
    PROPERTY_DECLARE_RW(Value, int, Test, SetValue, GetValue);
    PROPERTY_DECLARE_R(Name, string, Test, GetName);
    PROPERTY_DECLARE_W(WValue, int , Test, SetValue);
};
int main() 
{
    Test t(100);
    t.ShowValue();
    t.WValue = 999;            //只写属性可以写入
    //int i = t.WValue;        //只读属性无法读取
    t.Value = 200;            //读写属性可以写入
    int i = t.Value;        //读写属性可以读取
    cout << "i: " << i << std::endl;
    cout << t.Name << std::endl; //只读属性可以读取
    //t.Name = "hello";        //只写属性无法写入
 
    cin.get();
    return 0;
}
运行结果:
Value: 100
Set Value: 999
Set Value: 200
Get Value: 200
i: 200
TestClass
这种方法是类型安全的,但会让目标类占用更多内存,而且属性调用的函数必须为public的,另外为了让属性类能正确的取得目标类类指针,我使用了一个INIT_PROPERTY宏,这样比较麻烦,需要在构造函数中对每个属性调用一下,希望有更好办法的朋友告知.
一般来说对于标准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 int GetOld(void) | 
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下有用。
 
                
            
         
 
         浙公网安备 33010602011771号
浙公网安备 33010602011771号