Boolan C++研發工程師課程的作業真是越往後越難了。學了兩個月了,從小白走到現在,确實是提高了不少。筆芯侯捷老師。
/*題目:
設計一個Measurement計量機關類型,滿足如下要求,
1. 當為距離機關,當構造米或者千米等不同距離機關的執行個體時,統一以米為基本機關,
執行個體調用description函數傳回機關對應的meter類型(米類型)
2. 當為時間機關,當構造分鐘或者秒為機關的執行個體時,統一以秒為基本機關,
執行個體調用description函數傳回機關對應的second類型(秒類型)
3. 如果為除距離和時間的其他機關,都列印值即可。
提示
請使用Traits來完成該題,通過Traits擷取不同計量機關的轉換系數 和 基本機關。
用sprintf()函數将一個變量從int類型轉換到字元串類型
*/
#include "stdafx.h"
#include<iostream>
#include <iterator>
//<sstream>常用于格式轉換,他定義了三種類:istringstream、ostringstream和stringstream
//分别用來進行流的輸入、輸出和輸入輸出操作。
#include <sstream>
/*
定義函數模闆來将一個任意的類型轉換到特定的目标類型
template<class T>
void to_string(string & result,const T& t)
{
//建立一個流
ostringstream oss;
//把值傳遞如流中
oss<<t;
//使用str()成員函數來擷取流内部緩沖的一份拷貝
//擷取轉換後的字元轉并将其寫入result
result=oss.str();
}
這樣,你就可以輕松地将多種數值轉換成字元串了:
to_string(s1,10.5);//double到string
to_string(s2,123);//int到string
to_string(s3,true);//bool到string
*/
using namespace std;
// 定義類型萃取機type_traits
template<typename T>
class type_traits
{
public :
//将T::type_traits的類型名命名為valueType
typedef typename T::type_traits valueType;
};
class meter {
private:
string m_str;
public:
//将meter類型改名為type_traits
typedef meter type_traits;
// 定義靜态的轉換系數
static int m_convertData;
//構造函數
meter(string str) :m_str(str) {}
//類型轉換函數,為了在結尾加上機關
meter(double val, int con = 1)
{
/*
如果你打算在多次轉換中使用同一個stringstream對象,記住再每次轉換前要使用clear()方法;
在多次轉換中重複使用同一個stringstream(而不是每次都建立一個新的對象)對象最大的好處在于效率。
stringstream對象的構造和析構函數通常是非常耗費CPU時間的。
stringstream的轉換擁有類型安全和不會溢出的特性
*/
stringstream sstring;
// 輸入double類型數值,輸出string類型數值
//輸出值為:距離*轉換系數
sstring << val * con;
sstring >> m_str;
// 在輸出值末尾加上基本機關
m_str = m_str + "m";
}
//拷貝構造
meter(meter& met)
{
//擷取meter内的string資料
m_str = met.m_str;
}
// 重載運算符<<,作用:想讓cout輸出非标準庫中的類型,就要重載<<來使其可以識别自定義的類别
friend ostream& operator<<(ostream& os, const meter& str)
{
//擷取meter的私有string類型的資料m_str
os << str.getSting();
//将擷取的資料傳回
return os;
}
string getSting() const
{
//傳回meter的私有資料m_str
return m_str;
}
};
class kilometer {
public :
//将meter的類型名命名為type_traits
typedef meter type_traits;
// 定義靜态的轉換系數
static int m_convertData;
};
class second {
private:
string m_str;
public:
//将second的類型名命名為type_traits
typedef second type_traits;
// 定義靜态的轉換系數
static int m_convertData;
//構造函數
second(string str) :m_str(str) {}
//類型轉換
second(double val, int con = 1)
{
stringstream sstring;
//輸入double類型值,輸出string類型值
sstring << val * con;
sstring >> m_str;
// 在輸出值末尾加上基本機關
m_str = m_str + "s";
}
//拷貝構造函數
second(second& met)
{
m_str = met.m_str;
}
// 重載運算符<<,為了可以sout自定義類型
friend ostream& operator<<(ostream& os, const second& str)
{
os << str.getSting();
return os;
}
string getSting() const
{
return m_str;
}
};
class minute {
public:
//将second的類型名命名為type_traits
typedef second type_traits;
// 定義靜态的轉換系數
static int m_convertData;
};
//傳入參數的類型不确定,此時告知編譯器傳入的I是一個類型名
template<typename I>
class Measurement {
private:
double value;
public:
//構造函數
Measurement(double val) :value(val) {}
// 定義擷取機關類型對應數值函數
//函數的傳回值類型為type_traits<I>::valueType,即萃取出的傳入的類型參數I的類型
typename type_traits<I>::valueType description()
{
//定義type_traits<I>::valueType的類名為valType
//kilometer的valueType為meter,minute的valueType為second
//是以kilometer類和minute類不需要寫類型轉換函數,也不需要重載<<
typedef typename type_traits<I>::valueType valType;
//擷取不同計量機關的轉換系數
int iconv = I::m_convertData;
//調用對應的自定義類中的類型轉換函數
valType typeVal(value, iconv);
//傳回帶機關的string類型的字元串
return typeVal;
}
};
// 計量機關的泛化類型,因為傳入的類名可能不是我們定義的類
template<>
//這裡傳入的是double類型,是以偏特化double
class Measurement<double>
{
private:
double value;
public:
//構造函數
Measurement(double val) :value(val) {}
//除距離和時間的其他機關,列印其值。
string description()
{
stringstream sstring;
string str;
sstring << value;
sstring >> str;
return str;
}
};
//為轉化系數指派
int meter::m_convertData = 1;
int kilometer::m_convertData = 1000;
int second::m_convertData = 1;
int minute::m_convertData = 60;
int main()
{
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;
//想讓cout輸出非标準庫中的類型,就要重載<<來使其可以識别自定義的類别
cout << me << endl;
cout << m2.description() << endl;
cout << m3.description() << endl;
cout << m4.description() << endl;
cout << m5.description() << endl;
return 0;
}