boost的類型轉換

原來我總結過c++的一些類型轉換函數:http://blog.csdn.net/callmeback/article/details/4040583

static_cast, dynamic_cast, const_cast, reinterpret_cast其中各有各的用處和弊端。

boost的Conversion庫分別實現了四個類型轉換函數:polymorphic_case, polymorphic_downcast, numeric_cast和lexical_cast。
設計的主要原則是:代碼必須準確運行而且清晰的表達作者的意圖。
polynorphic_cast提供更好的類型安全性。在c++類型轉換中與dynamic_cast是類似的,只要看一眼polynorphic_cast的實現代碼就可以明白:polynorphic_cast調用了dynamic_cast,並且當返回值爲0時就是出錯的時候,所以polynorphic_cast直接拋出異常,節省了用戶的返回值判斷操作,實現的是邏輯的改進。

適用情況:當返回0不是錯誤的情況下,請用dynamic_cast;引用轉換請用dynamic_cast;剩下的推薦用polynorphic_cast。

template <class Target, class Source>
inline Target polymorphic_cast(Source* x BOOST_EXPLICIT_DEFAULT_TARGET)
{
    Target tmp = dynamic_cast<Target>(x);
    if ( tmp == 0 ) throw std::bad_cast();
    return tmp;
}


polynorphic_downcast提供更好的類型安全防護。從實現代碼來看polynorphic_downcast完全就是static_cast。由於static_cast比dynamic_cast效率更高,所以有用武之地,但是從來不保證轉換是合法的。polynorphic_downcast在debug模式下采用dynamic_cast測試了一下正確性,以求在release模式下默認爲正確的。但是不敢保證是正確的。所以我覺得,能不用就別用了。

template <class Target, class Source>
inline Target polymorphic_downcast(Source* x BOOST_EXPLICIT_DEFAULT_TARGET)
{
    BOOST_ASSERT( dynamic_cast<Target>(x) == x );  // detect logic error
    return static_cast<Target>(x);
}




numeric_cast顧名思義是數字轉換,提供安全的範圍檢查。數據類型有8位,16位,32位,64位等等,還分爲無符號和有符號兩種還有char。當從小內存向大內存轉換時往往很容易,返回來的時候往往會有出問題的隱患。而且有符號數和無符號數之間的轉換有時候並不是作者的真實意圖。

使用numeric_cast當數據截斷時輸出異常。而short s = 65537則不會。

#include <iostream>
#include <boost/cast.hpp>

int _tmain(int argc, _TCHAR* argv[])
{
	int num = 65537;
	try
	{
		short s = boost::numeric_cast<short>(num);
	}
	catch(boost::bad_numeric_cast& e)
	{
		std::cout << e.what() << std::endl;
	}

	getchar();
	return 0;
}

無符號數有迴繞功能,看以下代碼就可以看出。

#include <iostream>
#include <boost/cast.hpp>


int _tmain(int argc, _TCHAR* argv[])
{
	unsigned char max = 0xff;
	unsigned char maxmore = max + 1;
	unsigned char diff = maxmore - max;
	printf("max = %d, maxmore = %d, maxmore - max = %d\n",
		max, maxmore, diff);
	getchar();
	return 0;
}

無符號數和有符號數在相同數據位的情況下做類型轉換,numeric_cast會進行範圍判斷,不再舉例。

double向float轉換不會報錯,例如:

	double d = 0.123456789123456;
	float f = 0.123456;
	try
	{
		f = boost::numeric_cast<float>(d);
	}
	catch(boost::bad_numeric_cast& e)
	{
		std::cout << e.what();
	}

浮點數向整數轉換時截斷小數部分。

所以,使用numeric_cast的情況是:數據類型大小不一樣情況下進行復制和比較;無符號和有符號之間進行賦值和比較;從函數返回類型向數值變量賦值時。總之,一切有可能導致數據類型範圍變化的情況都應該使用。


lexical_cast提供文字轉換的服務。

 我們有很多情況下需要把字符串轉換成數值,把數值轉換成字符串。sprintf和atof、atol等等函數派上了用場而且不厭其煩的要判斷最終的返回結果是否是正確的。現在lexical_cast用一個函數解決了這些問題,並且在轉換錯誤時返回異常boost::bad_lexical_cast。

一個泛型代碼就替代了衆多的情況,不得不感嘆boost,我愛死你了。

#include <boost/lexical_cast.hpp>

template <typename T> std::string to_string(const T& t)
{
	try
	{
		return boost::lexical_cast<std::string>(t);
	}
	catch (boost::bad_lexical_cast& e)
	{
		return "";
	}
}


從字串到數值的正向反向轉換及其方便。還可以實現各種自定義類型的轉換,不過需要你自己實現了。

 

 

 

 

發佈了76 篇原創文章 · 獲贊 16 · 訪問量 47萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章