上面几篇文章中,我们添加了名称空间优化,添加事件功能。这些对我来说其实已经够了。但还可以加一个属性功能。
当我们在C++中更改一个属性时,平常都是Get函数加上Set函数,但是这样,没有直接写一个成员变量方便。例如:
a.SetValue(a.GetValue() + 1);没有
a.Value = a.Value + 1;方便。
但是这种方便只有在调用有属性功能的对象时才能使用。在创建属性的时候我还是用老套路,写一个Get和Set函数,该干啥还是干啥。我的属性功能其实就是在类中添加一个共有成员,读取这个数据成员的时候调用Get方法,给这个成员赋值的时候调用Set方法,当然这个成员在初始化的时候就要把Get和Set函数的指针传进来而且不能改变,因为我觉得没有必要去考虑换函数这些不可能发生的事情。
好了,思路都很明确了,现在该贴代码了。
template <typename T> class IProperty { public: virtual const T & Get() const = 0; virtual T & Reference() = 0; virtual void Set(const T &) = 0; }; template <typename T> class Property : public IProperty<T> { public: using Self = Property<T>; using GetConstantEventHandler = Delegate<const T &>; using GetNotConstantEventHandler = Delegate<T &>; using GetValueEventHandler = Delegate<T>; using SetEventHandler = Delegate<void, const T &>; public: Property() { } template <typename TClassType> Property(TClassType * className, const T & (TClassType::*getConstantFunction)() const, T &(TClassType::*getNotConstantFunction)(), void (TClassType::*setFunction)(const T & value)) { Clear(); mGetConstant.Add(className, getConstantFunction); mGetNotConstant.Add(className, getNotConstantFunction); mSet.Add(className, setFunction); } template <typename TClassType> Property(TClassType * className, const T & (TClassType::*getConstantFunction)() const, T &(TClassType::*getNotConstantFunction)()) { Clear(); mGetConstant.Add(className, getConstantFunction); mGetNotConstant.Add(className, getNotConstantFunction); } template <typename TClassType> Property(TClassType * className, const T & (TClassType::*getFunction)() const, void (TClassType::*setFunction)(const T & value)) { Clear(); mGetConstant.Add(className, getFunction); mSet.Add(className, setFunction); } template <typename TClassType> Property(TClassType * className, T & (TClassType::*getFunction)(), void (TClassType::*setFunction)(const T & value)) { Clear(); mGetNotConstant.Add(className, getFunction); mSet.Add(className, setFunction); } template <typename TClassType> Property(TClassType * className, const T & (TClassType::*getFunction)() const) { Clear(); mGetConstant.Add(className, getFunction); } template <typename TClassType> Property(TClassType * className, T & (TClassType::*getFunction)()) { Clear(); mGetNotConstant.Add(className, getFunction); } template <typename TClassType> Property(TClassType *className, void (TClassType::*setFunction)()) { Clear(); mSet.Add(className, setFunction); } public: void Clear() { mGetConstant.RemoveAll(); mGetNotConstant.RemoveAll(); mGetValue.RemoveAll(); mSet.RemoveAll(); } const T & Get() const override { if (IsConstReferenceGetable()) { return mGetConstant.Invoke(); } else { throw "Constant reference cannot get"; } } T & Reference() override { if (IsReferenceGetable()) { return mGetNotConstant.Invoke(); } else { throw "Cannot get"; } } void Set(const T & value) override { if (IsSetable()) { mSet.Invoke(value); } else if (IsReferenceGetable()) { Reference() = value; } else { throw "Cannot set"; } } bool IsGetable() const { return IsConstReferenceGetable() || IsReferenceGetable(); } bool IsConstReferenceGetable() const { return mGetConstant.GetCount() > 0; } bool IsReferenceGetable() const { return mGetNotConstant.GetCount() > 0; } bool IsSetable() const { return mSet.GetCount() > 0 || IsReferenceGetable(); } operator const T & () const { return Get(); } Self & operator = (const T & value) { Set(value); return *this; } private: GetConstantEventHandler mGetConstant; GetNotConstantEventHandler mGetNotConstant; GetValueEventHandler mGetValue; SetEventHandler mSet; }; template <typename T> class BasicProperty : IProperty<T> { public: using Self = BasicProperty<T>; public: BasicProperty() { } BasicProperty(const T & value) : mValue(value) { } public: const T & Get() const override { return mValue; } T & Reference() override { return mValue; } void Set(const T & value) { mValue = value; } operator const T & () const { return Get(); } Self & operator = (const T & value) { Set(value); return *this; } private: T mValue; };代码看上去很多,其实就两个类,一个Property,在初始化时将Get和Set函数传进去(当然还可以传一些为了效率而优化的函数,可惜这些函数太反人类了,几部不用),当然还是有缺陷的,我没有重载+=,-=,*=,/=这些运算符,也算是一大硬伤吧。还有一个是BasicProperty,简单的一个数据的封装,没有Get,Set之类的方法,在我看来很常用。
唉,怎么说呢,这次我添加属性这个功能其实我觉得是多此一举。在C++中完全可以用Get,Set方法来完成,即使有了属性功能也不常用。而且并没有省多少事。但是有的语言有这个功能就当是写着玩吧。
时间: 2024-10-04 15:53:27