前面实现了C++模拟C#属性机制,没有对属性的读写进行限制,都是可读且可写的,看了两篇参考文章后,便想实现对权限的控制,添加了一个权限的enum类型
typedef enum{
ReadWrite, /// default : both read and write are enabled
Readonly,
Writeonly
}PropertyAccess;
然后通过模板参数对其进行控制,在程序中对权限进行检测,如果没有相应权限则引发一个断言。改动不是太大,代码如下:
/* CppProperty * C++ simulated Property mechanism like C# property * with access control * Version 2.0 * Nocky @ 2008-04-11 */ #include #include #include #include #include using namespace std; #pragma warning(disable:4010) /// InvalidValueException class InvalidValueException : public exception { public : /// for build-in types template InvalidValueException(const T i) { msg= new char[BUFF_SIZE]; char buff[VAL_BUFF_SIZE]; _gcvt_s(buff, VAL_BUFF_SIZE,(float)i, VAL_BUFF_SIZE-2); strcpy_s(msg, BUFF_SIZE, "Invalid Value:"); strcat_s(msg,BUFF_SIZE, buff); } InvalidValueException(const string& v) { /// Here, you can't call /// InvalidValueException(const char* pc) /// like c#, If another constructor is called , / a temperory object will be created and / destroyed before the constructor called here returns. / Mybe a third common Initialization / function is the unique way Init(v.c_str()); } InvalidValueException(const char* pc) { Init(pc); } void Init(const char* pc) { assert(pc); if( ! pc ) pc = "Unknown Value"; msg = new char[BUFF_SIZE]; strcpy_s(msg,BUFF_SIZE, "Invalid Value :"); strcat_s( msg,BUFF_SIZE, pc); } ~InvalidValueException() { delete[] msg; } const char* what() const { return msg; } private: /// The two variable can also be decalared as not const / but still static, / so that client code can set the parameters dynamicly according / to actual conditions. static const int BUFF_SIZE = 150; static const int VAL_BUFF_SIZE = 20; char* msg; }; typedef enum{ ReadWrite, /// default : both read and write are enabled Readonly, Writeonly }PropertyAccess; /// Base class for all data type which can be used to define a Property / default constructor is accepted , custumized constructor / may be needed for / special data type(char* for example). template class Property { public: Property() { } Property(const V& v) { value = v; } virtual V operator=(const Property& src) { assert(rw!=Readonly); //if( rw == Readonly) throw exception("Readonly property can't be set!"); return operator=(src.value); } virtual V operator=(const V& p) { assert( rw!= Readonly); value = p; return value; } /// the following operators can just used to operate / the P of build-in types or those types / which have defined corresponding operation virtual V operator+(const V& p) { return value+p;} virtual Property& operator+=(const V& p) { assert(rw!=Readonly); //if( rw == Readonly) throw exception("Readonly property can't be set!"); value += p; return *this; } // data convention operator V() const{ // const is necessary assert(rw!=Writeonly); // if(rw == Writeonly) throw exception("Writeonly property can't be read!"); return value; } friend ostream& operator<< <>(ostream&s, const Property& v); protected: V value; }; template ostream& operator<<(ostream&s, const Property
& p) { s< Integer which is used to substitute int; template class Integer :public Property { public : Integer() :Property() { } Integer(int i) : Property(i) { } // overload operator= for value check if needed int operator=(const int& v) { if( v<= 0 || v>300){ throw InvalidValueException(v); } return Property::operator =(v); } }; /// A class representing a string, which can used as a Property class String: public Property { public: // overload operator= for value check if needed string operator=(const string& str) { if(str.size() <= 0) throw InvalidValueException(str); return Property::operator =(str); } // overload operator= for special data type string operator=(const char* pchar) { if(pchar == NULL) throw InvalidValueException(string("NULL")); return operator=(string(pchar)); } }; /// Student /// A concrete demo class for Property type, class Student { public: Integer<> Age; String Name; Integer Id; Student(int id,string name, int age) { //Id = id; // Error : readonly memcpy(&Id, &Integer(id), sizeof(Integer)); // unideal Name = name; Age = age; } friend ostream& operator<<(ostream& s, const Student& student); ~Student() { } }; ostream& operator<<(ostream& s, const Student& student) { s<