設計一個Measurement計量單位類型濒募,滿足如下要求坪郭,
- 當為距離單位吭产,當構(gòu)造米或者千米等不同距離單位的實例時侣监,統(tǒng)一以米為基本單位,實例調(diào)用description函數(shù)返回單位對應的meter類型(米類型)
- 當為時間單位臣淤,當構(gòu)造分鐘或者秒為單位的實例時达吞,統(tǒng)一以秒為基本單位,實例調(diào)用description函數(shù)返回單位對應的second類型(秒類型)
- 如果為除距離和時間的其他單位荒典,都打印值即可。
提示
請使用Traits來完成該題吞鸭,通過Traits獲取不同計量單位的轉(zhuǎn)換系數(shù)和基本單位寺董。
測試代碼measurement<meter> m1 = 20; measurement<kilometer> m2 = 11.2; meter me = m1.description(); measurement<second> m3 = 20; measurement<minute> m4 = 10; measurement<double> m5 = 10; std::cout << me << std::endl; std::cout << m2.description() << std::endl; std::cout << m3.description() << std::endl; std::cout << m4.description() << std::endl; std::cout << m5.description() << std::endl;
為了讓Measurement返回的descriptioni函數(shù)知道它對應的單位究竟是meter還是second,我們需要將泛化的類傳給Traits去獲得它所對應的基本單位刻剥。
因此遮咖,在type_traits.h
中,這樣寫
//
// Created by laixi on 2018/5/28.
//
#ifndef WEEK10HM_TYPE_TRAITS_H
#define WEEK10HM_TYPE_TRAITS_H
class meter;
class kilometer;
class second;
class minute;
class unit;
#include <type_traits>
#define const_value(x) std::integral_constant<int,x>
typedef std::integral_constant<bool, true> true_type;
typedef std::integral_constant<bool, false> false_type;
typedef const_value(1) one;
template <class type>
class type_traits {
public:
typedef false_type __is_time;
typedef false_type __is_length;
typedef one coefficient;
typedef type baseType;
};
template <>
class type_traits<meter> {
public:
typedef false_type __is_time;
typedef true_type __is_length;
typedef one coefficient;
typedef meter baseType;
};
template <>
class type_traits<kilometer> {
public:
typedef false_type __is_time;
typedef true_type __is_length;
typedef const_value(1000) coefficient;
typedef meter baseType;
};
template <>
class type_traits<second> {
public:
typedef true_type __is_time;
typedef false_type __is_length;
typedef one coefficient;
typedef second baseType;
};
template <>
class type_traits<minute> {
public:
typedef true_type __is_time;
typedef false_type __is_length;
typedef const_value(60) coefficient;
typedef second baseType;
};
#endif //WEEK10HM_TYPE_TRAITS_H
然后造虏,定義我的模板類measurement
//
// Created by laixi on 2018/5/28.
//
#ifndef WEEK10HM_MEASUREMENT_H
#define WEEK10HM_MEASUREMENT_H
#include "type_traits.h"
template <class U>
class measurement {
protected:
typename type_traits<U>::coefficient coeff;
U* _unit;
public:
explicit measurement();
explicit measurement(const measurement<U>& m);
measurement operator =(U u);
measurement operator =(measurement<U> m);
measurement operator =(float val){
_unit = new U(val);
}
U getUnit() const {return *this->_unit;};
float value() const {
return _unit->value;
};
typename type_traits<U>::baseType description();
operator double(){return coeff;};
measurement(float val){
_unit = new U(val);
};
template <typename T>
measurement operator= (T val){
if (!_unit) {
_unit = new U(val);
} else
*_unit = val;
}
};
template<class U>
measurement<U>::measurement(const measurement<U> &m) {
_unit = new U(*m._unit);
}
template<class U>
measurement<U> measurement<U>::operator=(U u) {
if (!_unit) {
_unit = new U(u);
return *this;
}
if (*_unit != u)
*_unit = u;
return *this;
}
template<class U>
measurement<U> measurement<U>::operator=(measurement<U> m) {
if (!_unit) {
_unit = new U(m.description());
return *this;
}
if (*_unit != m.description())
*_unit = m.description();
return *this;
}
template<class U>
measurement<U>::measurement() {
_unit = new U();
}
#endif //WEEK10HM_MEASUREMENT_H
為了讓measurement有具體的unit的概念御吞,我定義了一個基類unit
//
// Created by laixi on 2018/5/28.
//
#ifndef WEEK10HM_UNIT_H
#define WEEK10HM_UNIT_H
#include "type_traits.h"
#include <string>
#include "measurement.h"
typedef std::integral_constant<bool, true> true_type;
typedef std::integral_constant<bool, false> false_type;
typedef const_value(1) one;
class unit {
public:
float value;
std::string units;
public:
explicit unit(float val,std::string uni=""):units(uni),value(val){};
unit():units(""),value(0){};
unit(const unit& u){
value = u.value;
units = u.units;
};
//virtual unit& operator =(const unit& u) = 0;
unit&operator=(float val) {
value = val;
}
};
void output(std::ostream& os, unit u, true_type, false_type) {
os << u.value << u.units;
};
void output(std::ostream& os, unit u, false_type, true_type) {
os << u.value << u.units;
};
void output(std::ostream& os, unit u, false_type, false_type) {
os << u.value;
}
std::ostream& operator<<(std::ostream& os, unit u){
output(os, u, type_traits<unit>::__is_length(), type_traits<unit>::__is_time());
return os;
}
#endif //WEEK10HM_UNIT_H
然后通過基類來衍生出基本的時間類和長度類second和meter,為了方便漓藕,所有的子類都寫在meter.h中
//
// Created by laixi on 2018/5/28.
//
#ifndef WEEK10HM_METER_H
#define WEEK10HM_METER_H
#include "unit.h"
class meter: public unit {
public:
meter(float val=0):unit(val,"m"){};
//meter(unit& u):unit("m"){};
meter&operator=(const meter& m){
value = m.value;
};
//meter(float val):unit("m"),value(val){};
};
class kilometer: public unit {
public:
kilometer(float val=0):unit(val,"km"){};
//kilometer(float val):unit("km"),value(val){};
};
class second: public unit {
public:
second(float val=0):unit(val,"s"){};
//second(float val):unit("s"),value(val){};
};
class minute: public unit {
public:
minute(float val=0):unit(val,"m"){};
//minute(float val):unit("m"),value(val){};
};
template <class U>
meter getLengthBase(measurement<U> &m){
meter me = meter(m.value());
me.value = me.value * m;
return me;
}
template <class U>
second getTimeBase(measurement<U> &m){
second se = second(m.value());
se.value = se.value * m;
return se;
}
template <class U, class unit>
unit base_unit(measurement<U> &m,false_type,false_type){
return m.getUnit();
}
template <class U>
meter base_unit(measurement<U> &m,false_type,true_type){
return getLengthBase(m);
}
template <class U>
second base_unit(measurement<U> &m,true_type,false_type){
return getTimeBase(m);
}
template <class U>
typename type_traits<U>::baseType base_unit(measurement<U> &m,false_type,false_type){
return m.getUnit();
}
template <class U>
typename type_traits<U>::baseType measurement<U>::description() {
return base_unit(*this,typename type_traits<U>::__is_time(),typename type_traits<U>::__is_length());
}
template <class U>
std::ostream& operator<<(std::ostream& os, U u){
output(os, u, type_traits<U>::__is_length(), type_traits<U>::__is_time());
return os;
}
#endif //WEEK10HM_METER_H
最后陶珠,在main.cpp中按照題意輸入代碼,即可運行通過了享钞。
#include <iostream>
#include "meter.h"
int main() {
//std::cout << "Hello, World!" << std::endl;
measurement<meter> m1 = 20;
measurement<kilometer> m2 = 11.2;
meter me = m1.description();
measurement<second> m3 = 20;
measurement<minute> m4 = 10;
measurement<double> m5 = 10;
std::cout << me << std::endl;
std::cout << m2.description() << std::endl;
std::cout << m3.description() << std::endl;
std::cout << m4.description() << std::endl;
std::cout << m5.description() << std::endl;
return 0;
}
運行結(jié)果為
20m
11200m
20s
600s
10