cc

  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  38 随笔 :: 14 文章 :: 21 评论 :: 0 Trackbacks

1.问题
 在很多用C++开发服务器产品时,需要将不同的数据类型存储到一个容器中(有点类似HttpSession可以保存会话期间任意类型的数据),供其它使用程序查找。
 在Java和C#中这是一个简单的问题,可以使用Object对象来实现类型无关的数据结构,并且很好的解决了内存回收等问题。
 但C++中很难做到这一点,C++是一门静态类型语言,没有一个所有类型的基类。


2.一般方法
 一般解决这个问题的办法是使用void*指针来存储数据,象下面的代码:
 map<string,void*>
 但是这样带来几个问题:
 (1)因为C++在不知道类类型时无法正确的释放内存;
 (2)很多使用者使用它时,释放内存的时机难于确定;


3.让它正确释放内存
 我们可以定义一个公共的基类,让所有需要放到容器的类型继承它
 class Object
 {
 public:
  virtual ~Object(){cout<<"Object Destroy" << endl;}
 };
 由于使用了virtual析构函数因此可以确保delete obj的时可以正常工作。因此上面的容器定义变成了这样:
 map<string,Object*>


4.让它知道何时释放内存
 大家都知道,这时必须使用引用计数,不过很幸运有现成的,我们使用boost::share_ptr
 map<string,boost::share_ptr<Object*> >
 很好两个问题都已经解决,但如何向他们中加入C++的基本类型呢?


5.开发基本类型的封装类
 基本类型很多,如果每一个都写一个类,太累了,我们可以定义一个模板,这里的难点是基本类型之间的操作符重载,不同类型之间的运算返回的类型并不相同,这就需要写很多重载函数,在这里我们使用Loki来简化这些操作。使用Loki的TypeList来自动计算应该是什么返回值
 #include"Typelist.h" //Loki头文件
 template <typename T>
 class PrimerType:public Object
 {
 public:
  typedef T value_type;//基本类型
  typedef PrimerType<T> class_type;//基本类型的对象类型
 
 public:
  PrimerType()
   :m_value((value_type)0)
  {
  }
 
  template<typename Other>
   PrimerType(const Other& value)
   :m_value(value)
  {
  }
 
  ~PrimerType()
  {
   cout<<"PrimerType Destroy" << endl;
  }
 
  //基本类型转换操作符重载
  operator value_type() const
  {
   return m_value;
  }
 
  //赋值操作符重载
  const class_type& operator=(value_type value)
  {
   m_value=value;
   return *this;
  }
 
  bool operator!( ) const
  {
   return !m_value;
  }
 
  //作为类成员的算术运算符操作符重载
  class_type& operator++()
  {// ++ 前缀
   m_value+=1;
   return *this;
  }
  const class_type operator++(int)
  {// ++ 后缀
   class_type oldValue=*this;
   m_value+=1;
   return oldValue;
  }
  class_type& operator--()
  {// -- 前缀
   m_value-=1;
   return *this;
  }
  const class_type operator--(int)
  {// -- 后缀
   class_type oldValue=*this;
   m_value-=1;
   return oldValue;
  }
 
  class_type& operator+=(const value_type& value)
  {
   m_value+=value;
   return *this;
  }
  //。。。省略-= /= *= &= |= ^= %= 等等
 private:
  value_type m_value;
  friend istream& operator>><T> ( istream& is, class_type& ptvalue );
 };
 
 //流输入函数,不用输出(通过类型操作符重载自动完成)
 template<typename T>
 istream& operator>> ( istream& is, PrimerType<T>& ptvalue )
 {
  is >> ptvalue.m_value;
  return is;
 }
 //基本类型重定义
 typedef __int8  int8;
 typedef __int16 int16;
 typedef __int32 int32;
 typedef __int64 int64;
 typedef unsigned __int8 uint8;
 typedef unsigned __int16 uint16;
 typedef unsigned __int32 uint32;
 typedef unsigned __int64 uint64;
 
 
 //基本类型的对象类型
 typedef PrimerType<bool>   Boolean;
 typedef PrimerType<int8>   Int8;
 typedef PrimerType<int16>   Int16;
 typedef PrimerType<int32>   Int32;
 typedef PrimerType<int64>   Int64;
 typedef PrimerType<uint8>   UInt8;
 typedef PrimerType<uint16>   UInt16;
 typedef PrimerType<uint32>   UInt32;
 typedef PrimerType<uint64>   UInt64;
 typedef PrimerType<float>   Float;
 typedef PrimerType<double>   Double;
 typedef PrimerType<long>   Long;
 typedef PrimerType<unsigned long> ULong;
 //更友好的名字
 typedef Int8     Char;
 typedef Int16     Short;
 typedef Int32     Int;
 typedef UInt8     Byte;
 typedef UInt16     UShort;
 typedef UInt32     UInt;
 
 //算术运算返回类型的traits,运算时以排在后面的类型返回
 #define  PRIMERTYPELIST TYPELIST_13(bool,int8,uint8,int16,uint16,int32,uint32,long,unsigned long,int64,uint64,float,double)
 //                 |
 //                 int
 template <typename T1, typename T2>
 struct ResultType_Traits
 {
  enum { lefttype_index =::Loki::TL::IndexOf<PRIMERTYPELIST,T1>::value};
  enum { righttype_index =::Loki::TL::IndexOf<PRIMERTYPELIST,T2>::value};
  enum { resulttype_index = (lefttype_index>righttype_index)?lefttype_index:righttype_index};

//在vc7.1下int32以前的类型做算术运算都返回int32类型
  typedef typename ::Loki::TL::TypeAt<PRIMERTYPELIST, (resulttype_index<5)?5:resulttype_index >::Result  result_type;
 };

 
 //作为全局的算术运算符操作符重载 + - * /
 template<typename T1,typename T2>
 typename ResultType_Traits<T1,T2>::result_type operator +(const PrimerType<T1>& lhs,const T2& rhs)
 {
  return (T1)lhs+rhs;
 }
 
 template<typename T1,typename T2>
 typename ResultType_Traits<T1,T2>::result_type operator +(const T1& lhs,const PrimerType<T2>& rhs)
 {
  return lhs+(T2)rhs;
 }
 
 template<typename T1,typename T2>
 typename ResultType_Traits<T1,T2>::result_type operator +(const PrimerType<T1>& lhs,const PrimerType<T2>& rhs)
 {
  return (T1)lhs+(T2)rhs;
 }
 //。。。省略 - * /等等
 
 // 逻辑运算符重载
 template<typename T1,typename T2>
 bool operator ==(const PrimerType<T1>& lhs,const T2& rhs)
 {
  return (T1)lhs==rhs;
 }
 
 template<typename T1,typename T2>
 bool operator ==(const T1& lhs,const PrimerType<T2>& rhs)
 {
  return lhs==(T2)rhs;
 }
 
 template<typename T1,typename T2>
 bool operator ==(const PrimerType<T1>& lhs,const PrimerType<T2>& rhs)
 {
  return (T1)lhs==(T2)rhs;
 }
 //。。。省略 != >= 等等
 
 
6.小结
 使用对象来表示基本类型,由于使用了virtual的析构它是有内存浪费的,但在很多应用中它是很有用的。
 同时你可以增加String/DateTime的特化支持,这样就完整了
posted on 2008-07-10 14:44 醒目西西 阅读(1390) 评论(0)  编辑 收藏 引用 所属分类: 编程相关

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理