分析模式-計量的C++實現——完美版本 (轉)
以下是/develop/Article/14/14487.shtm">http://www.csdn.net/develop/Article/14/14487.shtm的一個改進版本,本來是作為評論附在上一篇文章後面的,但是作為評論發表的話,會丟失很多文字,很奇怪的說。本文是我和singleracer討論的結果,個人認為幾乎接近完美,希望能對大家有幫助,大家可以自己加入其它的單位體系和單位。
計量的模板類:
#ifndef _QUANTITY_H_
#define _QUANTITY_H_
#ifdef _DE
#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
struct UnitTraits {
typedef UnitType::Validator Validator;
};
template
class ValueTraits {
public:
static bool equal(const ValueType & l, const ValueType & r)
{return (l == r);}
};
template<>
class ValueTraits
public:
static bool equal(const double & l, const double & r)
{
static double precision = 0.000000001;
return (l - r < precision);
}
};
template<>
class ValueTraits
public:
static bool equal(const float & l, const float & r)
{
static float precision = 0.000000001f;
return (l - r < precision);
}
};
template
class Quantity
{
public:
typedef UnitValidator Validator;
template
: m_amount(amount), m_unit(Singleton< unit_wrap
{
ASSERT_SAME_TYPE(UnitTraits
}
~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
{
ASSERT_SAME_TYPE(UnitTraits
unit_base
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 {
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
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
class unit_wrap : public unit_base
{
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
};
#define QUANTITY Quantity
template
QUANTITY inline _cdecl operator+(const QUANTITY & a,
const QUANTITY & b)
{return (QUANTITY(a)+=b);}
template
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
/*
template
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
/*
template
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;
}
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-992498/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- C++完美實現Singleton模式[轉]C++模式
- 設計模式在Python中的完美實現設計模式Python
- C++設計模式:Singleton的模板實現之一 (轉)C++設計模式
- 設計模式——單例模式C++實現設計模式單例C++
- 設計模式——原型模式(C++)——演算法實現設計模式原型C++演算法
- 設計模式、用Delphi實現---->Builder模式 (轉)設計模式UI
- 原型模式的C++實現原型模式C++
- 命令模式(c++實現)模式C++
- 我所理解的設計模式(C++實現)——原型模式(Prototype Pattern)設計模式C++原型
- 我所理解的設計模式(C++實現)——建造者模式(Builder Pattern)設計模式C++UI
- 我所理解的設計模式(C++實現)——橋模式(Bridge Pattern)設計模式C++
- 設計模式、用Delphi實現---->Singleton 模式 (轉)設計模式
- 我所理解的設計模式(C++實現)——組合模式(Composite Pattern)設計模式C++
- 我所理解的設計模式(C++實現)——單例模式(Singleton Pattern)設計模式C++單例
- 詳解C++完美轉發C++
- 享元模式(c++實現)模式C++
- 中介者模式(c++實現)模式C++
- 橋接模式(c++實現)橋接模式C++
- 模板方法模式(c++實現)模式C++
- 狀態模式(c++實現)模式C++
- C++實現單例模式C++單例模式
- C++實現工廠模式C++模式
- 單例模式c++實現單例模式C++
- 23種設計模式:現代C++實現 V2.0設計模式C++
- AspectJ實現設計模式(三)——工廠方法模式 (轉)設計模式
- 我所理解的設計模式(C++實現)——介面卡模式(Adapter Pattern)設計模式C++APT
- 我所理解的設計模式(C++實現)——抽象工廠模式(Abstract Factory Pattern)設計模式C++抽象
- 我所理解的設計模式(C++實現)——工廠方法模式(Factory Method Pattern)設計模式C++
- 我對C++中THUNK一種實現技術的分析 (轉)C++
- 用Java實現的設計模式系列(1)-Factory (轉)Java設計模式
- 我所理解的設計模式(C++實現)——簡單工廠模式(Simple Factory Pattern)設計模式C++
- 輕量級分散式鎖的設計原理分析與實現分散式
- Semaphore-訊號量的實現分析
- 開發高質量的java程式碼;實現完美的人生Java
- C++左值右值完美轉發轉移C++
- MVC模式的PHP實現(3) (轉)MVC模式PHP
- C++物件導向特性實現機制的初步分析 Part3 (轉)C++物件
- C++物件導向特性實現機制的初步分析 Part1 (轉)C++物件