天天看點

STL第五周作業

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;
}

           

繼續閱讀