分享
 
 
 

分析模式-计量的C++实现——完美版本

王朝c/c++·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

以下是http://www.csdn.net/develop/Article/14/14487.shtm的一个改进版本,本来是作为评论附在上一篇文章后面的,但是作为评论发表的话,会丢失很多文字,很奇怪的说。本文是我和singleracer讨论的结果,个人认为几乎接近完美,希望能对大家有帮助,大家可以自己加入其它的单位体系和单位。

计量的模板类:

#ifndef _QUANTITY_H_

#define _QUANTITY_H_

#ifdef _DEBUG

#define ASSERT_SAME_TYPE( T1, T2) do {T1 v=T2();v; }while(false)

#else

#define ASSERT_SAME_TYPE( T1, T2)

#endif

#include "singleton.h"

template<class UnitType>

struct UnitTraits {

typedef UnitType::Validator Validator;

};

template<class ValueType>

class ValueTraits {

public:

static bool equal(const ValueType & l, const ValueType & r)

{return (l == r);}

};

template<>

class ValueTraits<double> {

public:

static bool equal(const double & l, const double & r)

{

static double precision = 0.000000001;

return (l - r < precision);

}

};

template<>

class ValueTraits<float> {

public:

static bool equal(const float & l, const float & r)

{

static float precision = 0.000000001f;

return (l - r < precision);

}

};

template<typename ValueType, class UnitValidator, class _Traits = ValueTraits<ValueType> >

class Quantity

{

public:

typedef UnitValidator Validator;

template<typename UnitType>Quantity(const ValueType & amount, const UnitType & )

: m_amount(amount), m_unit(Singleton< unit_wrap<UnitType, ValueType> >::Instance())

{

ASSERT_SAME_TYPE(UnitTraits<UnitType>::Validator, Validator);

}

~Quantity()

{

}

Quantity(const Quantity & other)

: m_amount(other.m_amount), m_unit(other.m_unit)

{

}

Quantity & operator=(const Quantity & rhs)

{

if(&rhs != this)

{

m_amount = rhs.m_amount;

m_unit = rhs.m_unit;

}

return *this;

}

template<typename UnitType> void convert(const UnitType & )

{

ASSERT_SAME_TYPE(UnitTraits<UnitType>::Validator, Validator);

unit_base<ValueType> * unit = Singleton< unit_wrap<UnitType, ValueType> >::Instance();

if(unit != m_unit)

{

m_amount = m_unit->to_standard(m_amount);

m_unit = unit;

m_amount = m_unit->from_standard(m_amount);

}

}

Quantity & operator+=(const Quantity & rhs)

{

m_amount += unitize( rhs );

return *this;

}

Quantity & operator-=(const Quantity & rhs)

{

m_amount -= unitize( rhs );

return *this;

}

bool operator==(const Quantity & rhs)

{

return _Traits::equal( m_amount, unitize(rhs));

}

bool operator>(const Quantity & rhs)

{

return m_amount > unitize( rhs );

}

bool operator>=(const Quantity & rhs)

{

return (m_amount > unitize( rhs ) ? true : (equal( m_amount, unitize(rhs))) );

}

bool operator<(const Quantity & rhs)

{

return m_amount < unitize( rhs );

}

bool operator<=(const Quantity & rhs)

{

return (m_amount < unitize( rhs ) ? true : (equal( m_amount, unitize(rhs))) );

}

private:

// 对于单位相同的运算不需要转换,也就没有丢失精度的问题

ValueType unitize( const Quantity & rhs )

{

if( m_unit == rhs.m_unit )

return rhs.m_amount;

else

return m_unit->from_standard(rhs.m_unit->to_standard(rhs.m_amount));

}

private:

template<typename ValueType>

class unit_base

{

public:

virtual ValueType to_standard(const ValueType & val) const = 0;

virtual ValueType from_standard(const ValueType & val) const = 0;

};

// 把unit_wrap设计为singleton,这样比较单位是否相同只需作简单的指针比较

template<typename UnitType, typename ValueType>

class unit_wrap : public unit_base<ValueType>

{

protected:

unit_wrap() {}

~unit_wrap() {}

public:

virtual ValueType to_standard(const ValueType & val) const

{

return UnitType::to_standard(val);

}

virtual ValueType from_standard(const ValueType & val) const

{

return UnitType::from_standard(val);

}

};

private:

ValueType m_amount;

unit_base<ValueType> * m_unit;

};

#define QUANTITY Quantity<ValueType,Validator,Traits>

template<typename ValueType,typename Validator,typename Traits>

QUANTITY inline _cdecl operator+(const QUANTITY & a,

const QUANTITY & b)

{return (QUANTITY(a)+=b);}

template<typename ValueType,typename Validator,typename Traits>

QUANTITY inline _cdecl operator-(const QUANTITY & a, const QUANTITY & b)

{return (QUANTITY(a)-=b);}

#endif /* _QUANTITY_H_ */

重量:

#ifndef _WEIGHT_H_

#define _WEIGHT_H_

#include "../Quantity.h"

class WeightValidator {};

typedef Quantity<double, WeightValidator> Weight;

/*

template<typename ValueType, typename UnitType>

Weight inline _cdecl operator*(const ValueType& value, const UnitType& unit )

{return Weight(value, unit);}

*/

class Kilogram

{

public:

typedef WeightValidator Validator;

static double to_standard(double val)

{return val;}

static double from_standard(double val)

{return val;}

};

class Gramme

{

public:

typedef WeightValidator Validator;

static double to_standard(double val)

{return val/1000.0;}

static double from_standard(double val)

{return val*1000.0;}

};

Kilogram _kg;

Gramme _g;

#endif /* _WEIGHT_H_ */

长度:

#ifndef _LENGTH_H_

#define _LENGTH_H_

#include "../Quantity.h"

class LengthValidator {};

typedef Quantity<double, LengthValidator> Length;

/*

template<typename ValueType, typename UnitType>

Length inline _cdecl operator*(const ValueType& value, const UnitType& unit )

{return Length(value, unit);}

*/

class Meter

{

public:

typedef LengthValidator Validator;

static double to_standard(double val)

{return val;}

static double from_standard(double val)

{return val;}

};

class Kilometer

{

public:

typedef LengthValidator Validator;

static double to_standard(double val)

{return val*1000.0;}

static double from_standard(double val)

{return val/1000.0;}

};

Meter _m;

Kilometer _km;

#endif /* _LENGTH_H_ */

测试代码:

// Quantity.cpp : Defines the entry point for the console application.

//

#include "stdafx.h"

#include "weight.h"

#include "length.h"

void testWeight()

{

Weight w1(1.0, _kg); //构造函数

Weight w2(1.0, _g); //构造函数

Weight w3 = w1; //拷贝构造函数

w3 = w2; //赋值操作

Weight w4(1.0, _kg);

w4 += w1; //相同单位相加

w4 += w2; //不同单位相加

Weight w5 = w4 + w1; //相同单位相加

w5 = w4 + w2; //不同单位相加

Weight w6(2.0, _kg);

w6 -= w1; //相同单位相减

w6 -= w2; //不同单位相减

Weight w7 = w5 - w1; //相同单位相减

w7 = w5 - w2; //不同单位相减

// 比较

Weight a(1.0, _kg);

Weight b(2.0, _kg);

Weight c(2000.0, _g);

Weight d(3000.0, _g);

bool f = (a < b);

f = (a < c);

f = (b==c);

f = (b < d);

//单位换算

Weight w10(1.0, _kg);

w10.convert(_g);

w10.convert(_kg);

}

void testLength()

{

Length l1(1.0, _km); //构造函数

Length l2(1.0, _m); //构造函数

Length l3 = l1; //拷贝构造函数

l3 = l2; //赋值操作

Length l4(1.0, _km);

l4 += l1; //相同单位相加

l4 += l2; //不同单位相加

Length l5 = l4 + l1; //相同单位相加

l5 = l4 + l2; //不同单位相加

Length l6(2.0, _km);

l6 -= l1; //相同单位相减

l6 -= l2; //不同单位相减

Length l7 = l5 - l1; //相同单位相减

l7 = l5 - l2; //不同单位相减

// 比较

Length a(1.0, _km);

Length b(2.0, _km);

Length c(2000.0, _m);

Length d(3000.0, _m);

bool f = (a < b);

f = (a < c);

f = (b==c);

f = (b < d);

//单位换算

Length l10(1.0, _km);

l10.convert(_m);

l10.convert(_km);

}

void testError()

{

#if(0)

Weight w1; // 没有缺省构造函数

Length l1; // 没有缺省构造函数

#endif

#if(0)

Weight w2(1.0, _km); //错误的单位

Length l2(1.0, _g); //错误的单位

#endif

#if(0)

Weight w3(1.0, _kg);

Length l3(1.0, _m);

w3.convert(_km); //错误的单位

l3.convert(_g); //错误的单位

#endif

#if(0)

Weight w4(1.0, _kg);

Length l4(1.0, _m);

w4 += l4; //错误的类型

w4 -= l4; //错误的类型

#endif

#if(0)

Weight w5(1.0, _kg);

Length l5(1.0, _m);

bool f = (w5 == l5);

f = (w5 > l5);

f = (w5 < l5);

#endif

}

int main(int argc, char* argv[])

{

testWeight();

testLength();

testError();

return 0;

}

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有