C++中的property库的设计与实现过程(二)——如何为属性指定get_和set_函数?
好了,现在就开始真正实现这个property库。我不打算一开始就把自己现有实现全盘托出,我希望记录整个设计的过程,这样,说不定在写这些文章的同时我还能找到进一步优化这个库的方法。
首先来想想,这个类应该怎么定义才好。
设想有这么一个类Sample,其中有一个属性X,那么代码可能要写成这样:
class Sample
{
int x_; // Is it necessary?
public:
int get_X() const
{
return x_;
}
int set_X(int value)
{
x_ = value;
return x_;
}
rdxLib::property_bag</* How to design? */> X;
Sample()
: X(/* How to initialize? */)
{
}
};这当然是仿造C#的属性写的C++代码,并不一定合理,但至少反映了一些现实:property_bag类(不叫property是因为怕与关键字冲突)必须是一个模板类,因为它是一个容器;必定有一个地方要把X和get_X与set_X关联起来,这个理由是显然的。
我首先想到的是在模板参数中指定get_X和set_X,就像这么定义:
namespace rdxLib {
template <typename Parent, typename Type, Type (Parent::*Get)()const, Type (Parent::*Set)(Type)>
class property_bag
{
typedef Type (Parent::*GetFunc)() const;
typedef Type (Parent::*SetFunc)(Type);
GetFunc get_;
SetFunc set_;
public:
property_bag()
: get_(Get)
, set_(Set)
{
}
};
}很酷不是么?刚写完之后有一种特别的成就感,嗯,C++ trick呢!
不过马上我就意识到问题了:
get 和set函数的返回值或参数的类型是Type明显不合理,如果是对象的话,应该使用Type &或const Type&才对。很不幸的是,从类型的角度来说,Type & (Parent::*Get)() const 与 Type (Parent::*Get)() const 是完全不兼容的!所以无论多酷,这都不能算是一种好方法!
于是我做了一些修改:
namespace rdxLib {
template <typename Parent, typename Type>
class property_bag
{
typedef property_bag<Parent, Type> MyType;
typedef const Type & (Parent::*Get)() const;
typedef Type & (Parent::*Set)(const Type &);
Get getFunction_;
Set setFunction_;
public:
property_bag(Get get, Set set)
: getFunction_(get)
, setFunction_(set)
{
}
};
}长长的模板参数不见了,而get和set函数的初始化位置改到构造函数中去,显得更加简洁。等等,成员函数的指针怎么调用呢?我需要一个Parent指针!所以还应该改改,加上Parent指针才对:
namespace rdxLib {
template <typename Parent, typename Type>
class property_bag
{
typedef property_bag<Parent, Type> MyType;
typedef const Type & (Parent::*Get)() const;
typedef Type & (Parent::*Set)(const Type &);
Parent * parent_;
Get getFunction_;
Set setFunction_;
public:
property_bag(Parent *parent, Get get, Set set)
: parent_(parent)
, getFunction_(get)
, setFunction_(set)
{
}
};
}完了么?远着呢!很显然,int与复杂类相比,get和set函数的声明肯定不同,我需要为所有的基础类型和指针类型、引用类型偏特化才行,所以这样的类肯定会有很多问题。
不过偏特化并不一定现在就要引入,因为麻烦,需要写一大堆一大堆的代码,首先还是针对int做一个简单的特化来看看效果好了,实现功能是第一位的呢。对int的特化代码就不贴了,仅仅是改了改typedef。
至此为止,get和set函数的大体位置就可以确定了。


有话想说?请留下评论吧~~如果喜欢我的blog,欢迎订阅~~
评论
还没有任何评论。
留下评论