原来我总结过c++的一些类型转换函数: http://www.uml.org.cn/c++/201212194.asp
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则不会。
<span style="font-size: 12px;">#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;
}</span> |
无符号数有回绕功能,看以下代码就可以看出。
<span style="font-size: 12px;">#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;
}
</span> |
无符号数和有符号数在相同数据位的情况下做类型转换,numeric_cast会进行范围判断,不再举例。
double向float转换不会报错,例如:
<span style="font-size: 12px;"> 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();
}</span> |
浮点数向整数转换时截断小数部分。
所以,使用numeric_cast的情况是:数据类型大小不一样情况下进行复制和比较;无符号和有符号之间进行赋值和比较;从函数返回类型向数值变量赋值时。总之,一切有可能导致数据类型范围变化的情况都应该使用。
lexical_cast提供文字转换的服务。
我们有很多情况下需要把字符串转换成数值,把数值转换成字符串。sprintf和atof、atol等等函数派上了用场而且不厌其烦的要判断最终的返回结果是否是正确的。现在lexical_cast用一个函数解决了这些问题,并且在转换错误时返回异常boost::bad_lexical_cast。
一个泛型代码就替代了众多的情况,不得不感叹boost,我爱死你了。
<span style="font-size: 12px;">#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 "";
}
}</span> |
从字串到数值的正向反向转换及其方便。还可以实现各种自定义类型的转换,不过需要你自己实现了。
|