首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

属性类DIY,该如何处理

2012-03-02 
属性类DIY在c++编程的时候,我们经常要把数据成员变量放到private区,以达到封装的目的,这样做的结果是,我们

属性类DIY
在c++编程的时候,我们经常要把数据成员变量放到private区,以达到封装的目的,这样做的结果是,我们有时候会需要手工产生很多的setxxx   getxxx函数。例如
class   point{
      private:
      double   x,y,z;
      public:
      point&   SetX(double   xx)   {x=xx;}
      double   GetX()   {return   x;}
      .................
};

最近研究了一下模板技术,可以模拟其他语言的属性简化以上的编程;我们可以写出下面的程序

template <class   T,   class   R>
class   Attribute{
      friend     class     T;//1......
R   val_;
Attribute(const   Attribute&   rhs):val_(rhs.val_)   {}
Attribute&   operator=(const   Attribute&   rhs)   {val_   =   rhs.val_;}
Attribute():val_(R())   {}
explicit   Attribute(R&   val):val_(val)   {}

public:
operator   R()   {return   val_;}
};

但是1处的代码是不符合标准的,我喜欢用gcc做编译器,于是找到下面的变通方案

template <class   T,   class   R>
class   Attribute{
      struct   proxy{
typedef   T   friend_class;       };
friend     class     proxy::friend_class;
R   val_;
Attribute(const   Attribute&   rhs):val_(rhs.val_)   {}
Attribute&   operator=(const   Attribute&   rhs)   {val_   =   rhs.val_;}
Attribute():val_(R())   {}
explicit   Attribute(R&   val):val_(val)   {}

public:
operator   R()   {return   val_;}
};

好了现在的代码可以编译通过了,我们可以放到实际工程中去应用了,很快又发现了问题,当用在内置类型的时候,这个方案还是很不错的,但是当用在用户自定义的类型上时,新的问题产生了。

class   inner{
    pubic:
        void   test()   {}
};
class   outer{
  public:
      Attribute <outer,inner>   in_;
      void   test()   {in_.val_.test();}   //1
};

我们可以看到在1处,对inner成员函数的调用形式有点太繁琐,显然不是我们所期望的,于是针对class,我们产生出如下的attribute方案。
通过私有派生的方式实现属性类。
template <class   T,class   R>
class   Attribute:R{
struct   proxy{
typedef   T   friend_class;
        };
friend     class     proxy::friend_class;

Attribute(const   Attribute&   rhs):R(rhs)   {}
Attribute&   operator=(const   Attribute&   rhs)   {R::operator   =(rhs);   return   *this;}

Attribute()   {}
Attribute(const   R&   val):R(val)   {}
public:
const   R&   Get()   {return   *this;}
};

现在我得到两个不同的解决方案,我们怎么把他们合并到一起呢,我们需要能够区分出一个类别是class还是内置类型。
翻翻boost库,在type_traits里面,我们发现有个is_class能够完成我们的要求。我们重新整理一下代码如下:

#include   "boost/type_traits/is_class.hpp "
namespace   gelib{
template <class   T,class   R,bool   isclass   =   boost::is_class <R> ::value   >
class   Attribute{
struct   proxy{
typedef   T   friend_class;
        };
friend     class     proxy::friend_class;
R   val_;
Attribute(const   Attribute&   rhs)   {val_   =   rhs.val_;}
Attribute&   operator=(const   Attribute&   rhs)   {val_   =   rhs.val_;   return   *this;}



Attribute():val_(R())   {}
Attribute(R   val):val_(val)   {}
public:
operator     R()   {return   val_;}
};

template <class   T,class   R>
class   Attribute <T,R,true> :R{
struct   proxy{
typedef   T   friend_class;
        };
friend     class     proxy::friend_class;

Attribute(const   Attribute&   rhs):R(rhs)   {}
Attribute&   operator=(const   Attribute&   rhs)   {R::operator   =(rhs);   return   *this;}

Attribute()   {}
Attribute(const   R&   val):R(val)   {}
public:
const   R&   Get()   {return   *this;}
};

}

利用模板的偏特化,我们实现了两个不同的Attribute模板。既然我们是在DIY学习阶段,不妨reinvent   wheel,研究一下boost,做个gcc编译器下的is_class简化形式,全部的代码实现如下:

namespace   gelib{
namespace   detail{
struct   yes   {char   val[2];};
struct   no   {};

template <class   U>  
yes   is_class_imp(void   (U::*)(void));
template <class   U>  
no   is_class_imp(...);

template <class   T>
struct   is_class{

static   const   bool   value   =   sizeof(detail::is_class_imp <T> (0))   ==   sizeof(detail::yes);
};
}
template <class   T,class   R,bool   isclass   =   detail::is_class <R> ::value   >
class   Attribute{
struct   proxy{
typedef   T   friend_class;
        };
friend     class     proxy::friend_class;
R   val_;
Attribute(const   Attribute&   rhs)   {val_   =   rhs.val_;}
Attribute&   operator=(const   Attribute&   rhs)   {val_   =   rhs.val_;   return   *this;}

Attribute():val_(R())   {}
Attribute(R   val):val_(val)   {}
public:
operator     R()   {return   val_;}
};

template <class   T,class   R>
class   Attribute <T,R,true> :R{
struct   proxy{
typedef   T   friend_class;
        };
friend     class     proxy::friend_class;

Attribute(const   Attribute&   rhs):R(rhs)   {}
Attribute&   operator=(const   Attribute&   rhs)   {R::operator   =(rhs);   return   *this;}

Attribute()   {}
Attribute(const   R&   val):R(val)   {}
public:
const   R&   Get()   {return   *this;}
};
}


[解决办法]
《Imperfect C++》里面好像有说这个问题。
[解决办法]
Imperfect C++的最后给出了属性的模拟。但无法达到内置属性的特性。
我也曾经尝试过,在C++03下,实现与内置属性相同的特性是不可能的。在C++09下,会好很多,但依然无法达到内置属性的要求。
http://community.csdn.net/Expert/TopicView3.asp?id=5536856和http://community.csdn.net/Expert/TopicView3.asp?id=5536878。这个帖子里尝试了几种方法,但用起来都不是很舒服。
不过,如果有了C++09的decltype,则会使最后一种方案更简单些。
[解决办法]
把“属性”加入标准可以说举手之劳,但是,有多大的价值呢?

热点排行