让我们的一切从代码开始吧,简单起见,代码省略std名字空间:
class MyObject {
object_id obj_id_;
class_id class_id_;
map<property_id, boost::any> properties_;
static const type_dict& getDict();
...
};
嗯,这是个从实际的项目中整理出来的代码,简单的说明一下:properties存放了Object的属性,MyObject底层依赖一个类型系统的支撑,这个类型系统的模型就是type_dict。class_id_是纪录一个对象实例所属的类型,obj_id_则是对象实例的ID.
这个对象的所有属性都是可以从外部访问的,但是,我不能把properties_公开,因为这样一来的话,外部就可以随便指定一个property_id插入map,而这个property_id也许并没有被当前class_id_所指类型包含,或者,根本就是非法值,这将导致MyObject内部不一致。
于是,我只能这么干:
public:
const_iterator begin() const{ return properties_.begin();}
iterator begin() { return properties_.begin();}
...
他们的实现都很简单,只不过是一行:调用properties的相应方法就是了,可我不得不重新写一遍,这是个copy&paste工作,总是让我想打瞌睡,结果,我总是出错,因为我总是忘记做一些必要的修改。如果有类似这样一种语法:
public:
proxy const_iterator properties_.begin() const;
或者:
proxy properties_.end;
我想我会愉快的多。除了少些一些代码外,关键是代码变得清晰了,程序员通常都是懒惰的,要命的我既懒惰又健忘,保持代码清晰对我而言很重要。于是,代码变成了这样:
class MyObject : private map<property_id, boost::any> {
typedef map<property_id, boost::any> ContType;
object_id obj_id_;
class_id class_id_;
//map<property_id, boost::any> properties_;
static const type_dict& getDict();
...
};
于是,我可以这么写:
public:
const_iterator begin() const{ return ContType::begin();}
iterator begin() { return ContType::begin();}
这样看上去语义至少清楚了一些,可是仍然不能让我满意,那个return 语句我还是可能弄错:我把上面两句c&v,然后把begin改成end,结果改漏了一个:(
最终,using达到了我的目的,我决定这么写:
public:
using ContType::begin;
using ContType::end;
using ContType::insert;
这么写不会导致访问权的问题,看,这和我最初设想的proxy properties_.end;多么相似。这样写的好处不仅仅是简单,最重要的是表达出来的语义:转调容器的相同方法。我想任何程序员首先都会相信STL的方法,而不是我写的,即使我的代码只有一行,也可能出错。using 方法如果出错的话,编译时就不会通过。
但是,using在这里很好的解决了我的问题,然而,他还是不能取代proxy。using无法让我有选择的代理函数的特定重载版本,例如我想公开const_iterator begin() const;而不公开iterator begin()就不能通过using实现。真希望C++会在语言层面支持proxy、delegate、reflection这样的特性,但是这种期望是在是不令人乐观。