C++属性注册机制

来源:互联网 发布:阿里云华南a和华南b 编辑:程序博客网 时间:2024/06/05 15:35
需求是这样:
假设我有Class Base是一个对任何使用者都可见的接口基类,现在某个对外完全封闭的模块有Class A : public Base,Class B : public Base等A、B、C.....等一系列对Base类的拓展和实现。使用者只能获得 Base* 指针类型,却不知道是A、B、C还是D哪个子类的具体实现。
我们需要让使用者通过Base*指针同样能操作(get、set)A、B、C的属性...........在实际编程中,这种设计其实很有用,我可以无限让用户拓展他自己组织的子类,而只要通过Base指针进行操作,对外部封闭了具体类型。
那么这个怎么实现呢?这里介绍前段时间学习得来的属性机制
属性,顾名思义,很容易联想到成员变量。那么要做到以上需求主要基类提供一个注册属性的机制就够了,不管子类有和属性,都可以通过基类继续注册,然后对外暴露

下面是属性基类的定义:

class PropertyBase{protected:PropertyBase(const Ogre::String& name, const Ogre::String& description, PropertyType type): mName(name),mDescription(description),mType(type){}PropertyBase(const PropertyBase& pro){}void operator= (const PropertyBase& pro){}public:virtual ~PropertyBase(){}const Ogre::String& getName() const { return mName; }const Ogre::String& getDescription() const { return mDescription; }PropertyType getType() const { return mType; }static PropertyType getTypeForValue(const short& val) { return PROP_SHORT; }static PropertyType getTypeForValue(const unsigned short& val) { return PROP_UNSIGNED_SHORT; }static PropertyType getTypeForValue(const int& val) { return PROP_INT; }.........protected:Ogre::String mName;Ogre::String mDescription;PropertyType mType;};下面是属性的定义:template <typename T>class Property : public PropertyBase{public:typedef PropertyGetterFunction<T> getter_func;typedef PropertySetterFunction<T> setter_func;Property(const Ogre::String& name, const Ogre::String& description, PropertyType type, getter_func getter, setter_func setter = setter_func()): PropertyBase(name,description,type),mGetter(getter),mSetter(setter){}virtual ~Property(void){}virtual void set(const T& val){if(!mSetter.isNull())mSetter(val);}virtual T get() const{return mGetter();}Ogre::Any getValue() const{return Ogre::Any(get());}protected:getter_func mGetter;setter_func mSetter;};


针对自定义类型(如结构体),我们也可以拆分为简单系统内置类型,所以添加一个属性集继承属性基类:

class PropertySet : public PropertyBase{public:typedef Ogre::map<Ogre::String, PropertyBase*>::type PropertyMap;typedef PropertyMap::value_type PropertyMapValue;typedef PropertyMap::iterator PropertyMapIter;PropertySet(const Ogre::String& name, const Ogre::String& description): PropertyBase(name,description,PROP_SET){}virtual ~PropertySet(){....}void addProperty(PropertyBase* prop){mPropertyMap.insert(PropertyMapValue(prop->getName(),prop));}PropertyBase* getProperty(const Ogre::String& name) const{if(mPropertyMap.find(name) == mPropertyMap.end())return NULL;return mPropertyMap.find(name)->second;}bool hasProperty(const Ogre::String& name) const{if(mPropertyMap.find(name) == mPropertyMap.end())return false;return true;}bool setAutoValue(const Ogre::String& name, const Ogre::String& value);template<typename T>void getValue(const Ogre::String& name, T& refVal) const{getPropertyImpl<T>(name,refVal,getTypeForValue(refVal));}template<typename T>void setValue(const Ogre::String& name, T& val){setPropertyImpl<T>(name,val,getTypeForValue(val));}PropertyMap getPropertyMap(){return mPropertyMap;}static bool matchPropertyStringSet(PropertySet& proSet, PropertyStringSet& proStrSet);protected:PropertyMap mPropertyMap;template <typename T>void setPropertyImpl(const Ogre::String& name, const T& val, PropertyType typeCheck){PropertyBase* baseProp = getProperty(name);if(baseProp->getType() == PROP_SET){。。。}else if (baseProp->getType() != typeCheck){。。。}static_cast<Property<T>*>(baseProp)->set(val);}template <typename T>void getPropertyImpl(const Ogre::String& name, T& refVal, PropertyType typeCheck) const{PropertyBase* baseProp = getProperty(name);if(baseProp->getType() == PROP_SET){。。。}else if (baseProp->getType() != typeCheck){。。。}refVal = static_cast<Property<T>*>(baseProp)->get(val);}};}}


现在为止,属性的定义就好了,符合属性用属性集表示。其实我们可以发现,我们需要注册的子类其实也就是一个属性集所以只要Class Base : PropertySet 那么这样就能满足需求。当然直接定义一个PropertySet作为成员变量也能满足需求这里介绍一下PropertyGetterFunction<T>和PropertySetterFunction<T>这两个类其实很类似与boost::Function,也就是对成员函数的封装当然我还可以定义一个一下的类,有注释就不详细说明了:

/***定义所有继承属性基类的对外接口*/class RENDERLIB_EXPORT PropertyClassBase{public:/**@fuction 构造*@paramrootName 属性集根名字*@paramdescription 属性集的描述*@time 2013/10/16 13:49:17*/PropertyClassBase(const Ogre::String& rootName, const Ogre::String& description){mPropertySet = new PropertySet(rootName,description);}/**@fuction 析构*@time 2013/10/16 13:50:10*/virtual ~PropertyClassBase(void){delete mPropertySet;mPropertySet = NULL;}/**@fuction 获取指定名字的子属性集合*@time 2013/10/16 13:27:59*/inline PropertySet* getChildPropertySet(const Ogre::String& name){PropertyBase* base = mPropertySet->getProperty(name);if( base->getType() == PROP_SET)return dynamic_cast<PropertySet*>(base);return NULL;}/**@fuction 获取属性*@time 2013/10/14 10:11:15*/template <typename T>inline Property<T>* getProperty(const Ogre::String& name){PropertyBase* base = mPropertySet->getProperty(name);if( base->getType() != PROP_SET)return dynamic_cast<Property<T>*>(base);}/**@fuction 查询属性是否存在*@time 2013/10/14 10:11:31*/inline bool hasProperty(const Ogre::String& name) const{return mPropertySet->hasProperty(name);}/**@fuction 智能匹配设置属性*@time 2013/10/15 17:11:11*/inline bool setAutoValue(const Ogre::String& name, const Ogre::String& value){return mPropertySet->setAutoValue(name,value);}/**@fuction 获取属性值*@time 2013/10/14 10:21:55*/template<typename T>inline void getValue(const Ogre::String& name, T& refVal) const{mPropertySet->getValue<T>(name,refVal);}/**@fuction 设置属性值*@time 2013/10/14 10:24:36*/template<typename T>inline void setValue(const Ogre::String& name, T& val){mPropertySet->setValue<T>(name,val);}/**@fuction 自动匹配PropertyStringSet里面的字符串值*@time 2013/10/16 14:13:03*/inline bool matchPropertyStringSet(PropertyStringSet& proStrSet){return PropertySet::matchPropertyStringSet(*mPropertySet,proStrSet);}/**@fuction 获取属性集合映射*@time 2013/10/14 10:30:27*/inline PropertySet::PropertyMap getPropertyMap() {return mPropertySet->getPropertyMap();}protected://属性集合PropertySet* mPropertySet;};


原创粉丝点击