C++中Boost的转换函数

Boost的转换函数是对C++中的四种类型转换函数(const_cast,reinterpret_cast,static_cast,dynamic_cast)的一些补充和扩展,在阅读本文前,请先熟悉C++中的四种类型转换函数相关知识。

polymorphic_cast

C++提供了dynamic_cast来实现运行时的类型转换,但是如果用来转换指针时,需要记得检查返回值(这是很多程序员容易忘掉的地方),否则一旦转换失败,将获得一个NULL指针,无异于给程序埋下了一个定时炸弹。

Boost的polymorphic_cast在dynamic_cast的基础上增加了对返回值的检测,如果转换失败,它就会抛出std::bad_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;
}

虽然抛异常增加了开销,但使用起来却更加简单了。

polymorphic_downcast

由于抛出异常会降低程序的效率,而且dynamic_cast更会查询一个type_info结构来确定正确的类型,所以不管是空间上的成本还是时间上的成本,都会大大增加。在一些应用场景中,只需要在编译期间进行类型转换即可。这时我们可以使用static_cast来实现编译期间的类型转换,但static_cast可能导致错误的类型转换:

struct A
{
    virtual ~A(){}
};

class B:public A{};
class C:public A{};

int main()
{
    A *pa = new C();
    B *pb = static_cast<B*>(pa);
}

对于上述程序,虽然pa和pb间没有继承关系,但是这个转换却可以通过,运行时也不会报任何错误,可一旦对pb进行访问,就会得到错误的结果甚至直接导致程序死掉。

polymorphic_downcast就巧妙的解决的这一问题,首先还是先看看它的定义:

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

从它的定义可以看出,在运行Release模式下,它和是static_cast一样的,也就是说它的Release版具有和static_cast一样的开销。但在Debug模式下,它会首先进行一次动态转换,而一旦类型不匹配,就会抛出异常。

在上述程序中,如果用polymorphic_downcast来替换static_cast的话,我们可以先在Debug模式下运行程序,如果有错误的类型转换,将很容易的检测出来。待改正所有的错误后,再发布Release版,这样即没有动态转换造成的开销,又杜绝了错误的类型转换。

boost::numeric_cast

在c++中,我们经常需要把不同类型的数字互相转换,如将一个数字在long和short之间转换。但由于各数字的精度不同,当一个数字从"大"类型到"小"类型就可能导致转换失败,如下所示:

long n1 = 99999999;
short n2 = static_cast<short>(n1);

对于如上转换,n2得到的是一个负数,显然这个不是我们所期望的,并且这种运行时的错误是很难检测的,一旦使用了这个错误的转换后的数据,后果不堪设想。

boost::numeric_cast可以帮助我们解决这一问题,对于上面的转换,boost::numeric_cast会抛出一个boost:: bad_numeric_cast这个异常对象。从而保证转换后值的有效性。上述代码可以改写为如下:

try
{
    long n1 = 99999999;
    short n2 = boost::numeric_cast<short>(n1);
}
catch(boost::bad_numeric_cast&)
{
    std::cout<<"The conversion failed"<<std::endl;
}

numeric_cast是如何知道这样的数字转换失败的呢?numeric_cast合理的应用了std::numeric_limits<>,而std::numeric_limits<>就是内建数字类型的type_tratis。当然也可以将自己定义的数字抽象类型添加到std::numeric_limits<>的特化版本中,这样numeric_cast就可以作用于自定义的类型了。由于相对复杂点,本文是介绍其功能和用法,就不分析其源码了,感兴趣的朋友可以参看boost文档和代码。

对于numeric_cast的使用也是有些要求的。

  • 源类型和目标类型必须都是可拷贝构造的
  • 源类型和目标类型必须都是数字型类型。也就是被std::numeric_limits<>::is_specialized的特化定义为true
  • 源类型必须能被static_cast转换为目标类型

其实对我们用的系统内置的数字来说,这几条都不是限制,只有我们在需要通过它转换自定义的数据类型时,才需要注意,否则编译不通过(其实这个错误还比较好发现和解决)。

boost::lexical_cast

在C/C++程序开发中,往往需要将数字型对象的值转换为字符文本格式,或反之操作。虽然C语言就提供了不少系统函数来进行这种操作,如scanf、atoi等。这些函数小巧简洁,使用很方便,但缺少扩展性。在std中引入了stringstream来以一个通用的方式实现各种转换,但缺少对错误转换的检测。而boost::lexical_cast是在stringstream上的一个扩展,增加了对错误的类型转换的检测:

#include <string>
#include <iostream>
#include <boost/lexical_cast.hpp>

using namespace std;

int main()
{
    try
    {
        int i = 100;
        string str = boost::lexical_cast<string>(i);
        cout<<"The string is:"<<str<<endl;
        str = "error";
        i = boost::lexical_cast<int>(str);
    }
    catch(boost::bad_lexical_cast& exobj)
    {
        cout<<"Convert err:"<<endl;
        cout<<exobj.what()<<endl;
    }
}

在上述转换中,第二个转换从"err"到int的转换是失败的,会抛出一个boost::bad_lexical_cast的异常,从而能帮助我们构造更安全稳定的程序。

boost::lexical_cast内部实现其实也是一个stringstream的封装,其函数简化如下:

template<typename Target,typename Source>
Target lexical_cast(Source arg){
    detail::lexical_stream<Target,Source> interpreter;
    Target result;
    if(!(interpreter<<arg && interpreter>>result))
        throw_exception(bad_lexical_cast(typeid(Target),typeid(Source)));
    return result;
}

其中lexical_stream<>对字符串流做了一系列的包装,主要提供了operator<<(Source)和operator>>(Target)操作,用于判断操作是否成功。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • C++ boost::asio编程-异步TCP详解及实例代码

    C++ boost::asio编程-异步TCP 大家好,我是异步方式 和同步方式不同,我从来不花时间去等那些龟速的IO操作,我只是向系统说一声要做什么,然后就可以做其它事去了.如果系统完成了操作, 系统就会通过我之前给它的回调对象来通知我. 在ASIO库中,异步方式的函数或方法名称前面都有"async_ " 前缀,函数参数里会要求放一个回调函数(或仿函数).异步操作执行 后不管有没有完成都会立即返回,这时可以做一些其它事,直到回调函数(或仿函数)被调用,说明异步操作已经完成. 在ASI

  • C++之Boost::array用法简介

    本文实例讲述了c++里支持静态数组的容器:boost.array.分享给大家供大家参考.具体分析如下: 很多C++程序员都认为boost.array很有可能出现在下一代标准库里.对于boost.array的用法有一个基本的了解是很有必要的. 1. 为什么我们需要固定大小的数组的容器 首先,固定大小的数组还是很常见的,虽然stl提供了vector,但是vector作为动态可增长的数组,比静态数组多了一点开销,这在一些人看来是无法忍受的.c++里也需要提供固定大小容量的数组容器,当然,性能可以和普通

  • 浅析C++中boost.variant的几种访问方法

    Boost.Variant Variant库包含一个不同于union的泛型类,用于在存储和操作来自于不同类型的对象.这个库的一个特点是支持类型安全的访问,减少了不同数据类型的类型转换代码的共同问题. Variant 库如何改进你的程序? •对用户指定的多种类型的进行类型安全的存储和取回 •在标准库容器中存储不同类型的方法 •变量访问的编译期检查 •高效的.基于栈的变量存储 Variant 库关注的是对一组限定类型的类型安全存储及取回,即非无类的联合.Boost.Variant 库与 Boost.

  • C++之BOOST字符串查找示例

    本文实例讲述了C++中BOOST字符串查找的方法,分享给大家供大家参考.具体方法如下: BOOST  字符串查找示例 复制代码 代码如下: #include <string>  #include <iostream>  #include <algorithm>  #include <functional>  #include <boost/algorithm/string/case_conv.hpp>  #include <boost/al

  • C++ boost::asio编程-同步TCP详解及实例代码

    boost::asio编程-同步TCP boost.asio库是一个跨平台的网络及底层IO的C++编程库,它使用现代C++手法实现了统一的异步调用模型. boost.asio库支持TCP.UDP.ICMP通信协议. 下面介绍同步TCP模式: 大家好!我是同步方式! 我的主要特点就是执着!所有的操作都要完成或出错才会返回,不过偶的执着被大家称之为阻塞,实在是郁闷~~(场下一片嘘声),其实这样 也是有好处的,比如逻辑清晰,编程比较容易. 在服务器端,我会做个socket交给acceptor对象,让它

  • C++ boost::asio编程-域名解析详细介绍

    C++ boost::asio编程-域名解析 在网络通信中通常我们并不直接使用IP地址,而是使用域名.这时候我们就需要用reslover类来通过域名获取IP,它可以实现 与IP版本无关的网址解析. #include "stdafx.h" #include "boost/asio.hpp" #include "boost/shared_ptr.hpp" #include "boost/thread.hpp" #include &

  • C++之boost::array的用法

    本文实例讲述了C++之boost::array的用法,分享给大家供大家参考.具体如下: 复制代码 代码如下: #include <string>  #include <iostream>  #include <boost/array.hpp>  #include <algorithm>  using namespace std;  int main()  {      boost::array<int, 5> array_temp = {{12,

  • C++中Boost的转换函数

    Boost的转换函数是对C++中的四种类型转换函数(const_cast,reinterpret_cast,static_cast,dynamic_cast)的一些补充和扩展,在阅读本文前,请先熟悉C++中的四种类型转换函数相关知识. polymorphic_cast C++提供了dynamic_cast来实现运行时的类型转换,但是如果用来转换指针时,需要记得检查返回值(这是很多程序员容易忘掉的地方),否则一旦转换失败,将获得一个NULL指针,无异于给程序埋下了一个定时炸弹. Boost的pol

  • JavaScript中的object转换函数toString()与valueOf()介绍

    JavaScript中,object转换为boolean的操作非常简单:所有的object转换成boolean后均为true:即使是new Boolean(false)这样的object在转换为boolean后仍然为true. 复制代码 代码如下: var x = new Boolean(false); if(x){   console.log("x is true"); } 在将object转换为string或者number时,JavaScript会调用object的两个转换函数:t

  • C#中HTML字符转换函数分享

    因此需要以下函数做转换: 复制代码 代码如下: ///<summary> ///替换html中的特殊字符 ///</summary> ///<paramname="theString">需要进行替换的文本.</param> ///<returns>替换完的文本.</returns> public static string HtmlEncode(string theString) { theString=theSt

  • php中的字符编码转换函数用法示例

    本文实例讲述了php中的字符编码转换函数的用法,分享给大家供大家参考.具体实现方法如下: 一般来说,在网页程序中,尤其是涉及到数据库的读出过程中,往往最恼火的就是字符编码的问题,php4.0.6以上的版本提供了mb_convert_encoding 可以方便的转换编码. 具体如下: 复制代码 代码如下: <?php /* Convert internal character encoding to SJIS */ $str = mb_convert_encoding($str, "SJIS

  • 关于PHP中字符串与多进制转换函数的实例代码

    转换函数 /** * [字符串转换为(2,8,16进制)ASCII码] * @param string $str [待处理字符串] * @param boolean $encode [字符串转换为ASCII|ASCII转换为字符串] * @param string $intType [2,8,16进制标示] * @return string byte_str [处理结果] * @author alexander */ function strtoascii($str, $encode=true,

  • 基于Java中进制的转换函数详解

    十进制转成十六进制: Integer.toHexString(int i) 十进制转成八进制 Integer.toOctalString(int i) 十进制转成二进制 Integer.toBinaryString(int i) 十六进制转成十进制 Integer.valueOf("FFFF",16).toString() 八进制转成十进制 Integer.valueOf("876",8).toString() 二进制转十进制 Integer.valueOf(&qu

  • opencv中颜色空间转换函数cv2.cvtColor()使用

    opencv中有多种色彩空间,包括 RGB.HSI.HSL.HSV.HSB.YCrCb.CIE XYZ.CIE Lab8种,使用中经常要遇到色彩空间的转化,以便生成mask图等操作. 可以使用下面的色彩空间转化函数 cv2.cvtColor( )进行色彩空间的转换: HSV 表示hue.saturation.value image_hsv = cv2.cvtColor(image,cv2.COLOR_BGR2HSV) 用这个函数把图像从RGB转到HSV夜色空间,注意是BGR2HSV,因为在ope

  • C++中Boost.Chrono时间库的使用方法

    前言 大家应该都有所体会,时钟这个东西在程序中扮演者重要的角色,在系统编程的时候睡眠.带超时的等待.带超时的条件变量.带超时的锁都会用到,但是往往对特定系统依赖性很大,感觉即使不考虑系统的跨平台性,如果能使用一个稳定的接口,同时如果能够方便的对时刻.时段等进行相关的操作和运算,将是再好不过的了. 在boost库中和时间相关的库有Boost.DateTime和Boost.Chrono,前者专注于时间时刻以及本地化相关的内容,而后者主要是时刻.时长和时间的计算等内容.当然,C++11标准已经支持st

  • C++中Boost的智能指针weak_ptr

    循环引用: 引用计数是一种便利的内存管理机制,但它有一个很大的缺点,那就是不能管理循环引用的对象.一个简单的例子如下: #include <string> #include <iostream> #include <boost/shared_ptr.hpp> #include <boost/weak_ptr.hpp> class parent; class children; typedef boost::shared_ptr<parent> p

  • C++ 中boost::share_ptr智能指针的使用方法

    C++ 中boost::share_ptr智能指针的使用方法 最近项目中使用boost库的智能指针,感觉智能指针还是蛮强大的,在此贴出自己学习过程中编写的测试代码,以供其他想了解boost智能指针的朋友参考,有讲得不正确之处欢迎指出讨论.当然,使用boost智能指针首先要编译boost库,具体方法可以网上查询,在此不再赘述. 智能指针能够使C++的开发简单化,主要是它能够自动管理内存的释放,而且能够做更多的事情,即使用智能指针,则可以再代码中new了之后不用delete,智能指针自己会帮助你管理

随机推荐