1. 程式人生 > >跟陳灣來完善C++(2), 添加屬性功能

跟陳灣來完善C++(2), 添加屬性功能

ack play splay 即使 name eve itl move pla

上面幾篇文章中,我們添加了名稱空間優化,添加事件功能。這些對我來說其實已經夠了。但還可以加一個屬性功能。


當我們在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方法來完成,即使有了屬性功能也不常用。而且並沒有省多少事。但是有的語言有這個功能就當是寫著玩吧。


技術分享

跟陳灣來完善C++(2), 添加屬性功能