C++ Boost Conversion超详细讲解

   2023-02-09 学习力0
核心提示:目录一、说明二、示例和代码三、更多示例代码一、说明Boost.Conversion 在头文件 boost/cast.hpp 中定义了转换运算符 boost::polymorphic_cast 和 boost::polymorphic_downcast。它们旨在更精确地处理类型转换——通常使用 dynamic_cast 完成。库由两个文件组

一、说明

Boost.Conversion 在头文件 boost/cast.hpp 中定义了转换运算符 boost::polymorphic_cast 和 boost::polymorphic_downcast。它们旨在更精确地处理类型转换——通常使用 dynamic_cast 完成。

库由两个文件组成。分别在boost/cast.hpp文件中定义了boost::polymorphic_castboost::polymorphic_downcast这两个类型转换操作符, 在boost/lexical_cast.hpp文件中定义了boost::lexical_cast

二、示例和代码

boost::polymorphic_castboost::polymorphic_downcast是为了使原来用dynamic_cast实现的类型转换更加具体。具体细节,如下例所示。

struct father 
{ 
  virtual ~father() { }; 
}; 
struct mother 
{ 
  virtual ~mother() { }; 
}; 
struct child : 
  public father, 
  public mother 
{ 
}; 
void func(father *f) 
{ 
  child *c = dynamic_cast<child*>(f); 
} 
int main() 
{ 
  child *c = new child; 
  func(c); 
  father *f = new child; 
  mother *m = dynamic_cast<mother*>(f); 
} 

本例使用dynamic_cast类型转换操作符两次: 在func()函数中,它将指向父类的指针转换为指向子类的指针。在main()中, 它将一个指向父类的指针转为指向另一个父类的指针。第一个转换称为向下转换(downcast),第二个转换称为交叉转换(cross cast)。

通过使用 Boost.Conversion 的类型转换操作符,可以将向下转换和交叉转换区分开来。

#include <boost/cast.hpp> 
struct father 
{ 
  virtual ~father() { }; 
}; 
struct mother 
{ 
  virtual ~mother() { }; 
}; 
struct child : 
  public father, 
  public mother 
{ 
}; 
void func(father *f) 
{ 
  child *c = boost::polymorphic_downcast<child*>(f); 
} 
int main() 
{ 
  child *c = new child; 
  func(c); 
  father *f = new child; 
  mother *m = boost::polymorphic_cast<mother*>(f); 
} 

boost::polymorphic_downcast
 类型转换操作符只能用于向下转换。 它内部使用 
static_cast
 实现类型转换。 由于 
static_cast
 并不动态检查类型转换是否合法,所以 
boost::polymorphic_downcast
 应该只在类型转换是安全的情况下使用。 在调试(debug builds)模式下, 
boost::polymorphic_downcast
 实际上在 
assert ()
函数中使用
 dynamic_cast
 验证类型转换是否合法。 请注意这种合法性检测只在定义了
NDEBUG
宏的情况下执行,这通常是在调试模式下。

向下转换最好使用boost::polymorphic_downcast, 那么boost::polymorphic_cast就是交叉转换所需要的了。 由于dynamic_cast是唯一能实现交叉转换的类型转换操作符,boost::polymorphic_cast内部使用了它。 由于boost::polymorphic_cast能够在错误的时候抛出std::bad_cast类型的异常,所以优先使用这个类型转换操作符还是很有必要的。相反,dynamic_cast在类型转换失败使将返回0。 避免手工验证返回值,boost::polymorphic_cast提供了自动化的替代方式。

boost::polymorphic_downcastboost::polymorphic_cast只在指针必须转换的时候使用;否则,必须使用dynamic_cast执行转换。 由于boost::polymorphic_downcast是基于static_cast,所以它不能够,比如说,将父类对象转换为子类对象。 如果转换的类型不是指针,则使用boost::polymorphic_cast执行类型转换也没有什么意义,而在这种情况下使用dynamic_cast还会抛出一个std::bad_cast异常。

虽然所有的类型转换都可用dynamic_cast实现,可boost::polymorphic_downcastboost::polymorphic_cast也不是真正随意使用的。 Boost.Conversion 还提供了另外一种在实践中很有用的类型转换操作符。 体会一下下面的例子。

#include <boost/lexical_cast.hpp> 
#include <string> 
#include <iostream> 
int main() 
{ 
  std::string s = boost::lexical_cast<std::string>(169); 
  std::cout << s << std::endl; 
  double d = boost::lexical_cast<double>(s); 
  std::cout << d << std::endl; 
} 

类型转换操作符boost::lexical_cast可将数字转换为其他类型。 例子首先将整数169转换为字符串,然后将字符串转换为浮点数。

boost::lexical_cast内部使用流(streams)执行转换操作。 因此,只有那些重载了operator<<()operator>>()这两个操作符的类型可以转换。 使用boost::lexical_cast的优点是类型转换出现在一行代码之内,无需手工操作流(streams)。 由于流的用法对于类型转换不能立刻理解代码含义, 而boost::lexical_cast类型转换操作符还可以使代码更有意义,更加容易理解。

请注意boost::lexical_cast并不总是访问流(streams);它自己也优化了一些数据类型的转换。

如果转换失败,则抛出boost::bad_lexical_cast类型的异常,它继承自std::bad_cast

#include <boost/lexical_cast.hpp> 
#include <string> 
#include <iostream> 
int main() 
{ 
  try 
  { 
    int i = boost::lexical_cast<int>("abc"); 
    std::cout << i << std::endl; 
  } 
  catch (boost::bad_lexical_cast &e) 
  { 
    std::cerr << e.what() << std::endl; 
  } 
} 

三、更多示例代码

本例由于字符串 "abc" 不能转换为int类型的数字而抛出异常。

示例 54.1。使用 dynamic_cast 向下和交叉投射

struct base1 { virtual ~base1() = default; };
struct base2 { virtual ~base2() = default; };
struct derived : public base1, public base2 {};
void downcast(base1 *b1)
{
  derived *d = dynamic_cast<derived*>(b1);
}
void crosscast(base1 *b1)
{
  base2 *b2 = dynamic_cast<base2*>(b1);
}
int main()
{
  derived *d = new derived;
  downcast(d);
  base1 *b1 = new derived;
  crosscast(b1);
}

Example54.1

示例 54.1 两次使用了转换运算符 dynamic_cast:在 downcast() 中,它将指向基类的指针转换为指向派生类的指针。在 crosscast() 中,它将指向基类的指针转换为指向不同基类的指针。第一个转换是向下转换,第二个转换是交叉转换。 Boost.Conversion 中的转换运算符让您可以区分向下转换和交叉转换。

示例 54.2。使用 polymorphic_downcast 和 polymorphic_cast 进行向下和交叉转换

#include <boost/cast.hpp>
struct base1 { virtual ~base1() = default; };
struct base2 { virtual ~base2() = default; };
struct derived : public base1, public base2 {};
void downcast(base1 *b1)
{
  derived *d = boost::polymorphic_downcast<derived*>(b1);
}
void crosscast(base1 *b1)
{
  base2 *b2 = boost::polymorphic_cast<base2*>(b1);
}
int main()
{
  derived *d = new derived;
  downcast(d);
  base1 *b1 = new derived;
  crosscast(b1);
}

boost::polymorphic_downcast(参见示例 54.2)只能用于向下转型,因为它使用 static_cast 来执行转换。因为 static_cast 不会动态检查转换的有效性,boost::polymorphic_downcast 必须仅在转换安全时使用。在调试版本中,boost::polymorphic_downcast 使用 dynamic_cast 和 assert() 来确保类型转换有效。只有在未定义宏 NDEBUG 时才会执行此测试,这通常是调试版本的情况。

boost::polymorphic_cast 是交叉转换所必需的。 boost::polymorphic_cast 使用 dynamic_cast,它是唯一可以执行交叉转换的转换运算符。最好使用 boost::polymorphic_cast 而不是 dynamic_cast,因为前者在出现错误时抛出 std::bad_cast 类型的异常,而 dynamic_cast 在类型转换失败时返回空指针。

仅使用 boost::polymorphic_downcast 和 boost::polymorphic_cast 来转换指针;否则,使用 dynamic_cast。因为 boost::polymorphic_downcast 是基于 static_cast 的,所以它不能将基类的对象转换为派生类的对象。此外,使用 boost::polymorphic_cast 转换指针以外的类型没有意义,因为如果转换失败,dynamic_cast 将抛出 std::bad_cast 类型的异常。

原文地址:https://yamagota.blog.csdn.net/article/details/128011162
 
标签: C++ Boost Conversion
反对 0举报 0 评论 0
 

免责声明:本文仅代表作者个人观点,与乐学笔记(本网)无关。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
    本网站有部分内容均转载自其它媒体,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责,若因作品内容、知识产权、版权和其他问题,请及时提供相关证明等材料并与我们留言联系,本网站将在规定时间内给予删除等相关处理.

  • Aurelius vs mORMot vs EntityDAC Delphi 的
    Aurelius vs mORMot vs EntityDAC   Delphi 的 ORM框架:http://www.tmssoftware.com/site/aurelius.asp#product-buy-onlinehttps://synopse.info/fossil/wiki/Synopse+OpenSourcehttps://www.devart.com/entitydac/download.htmlkbmMW  http://www.compo
    02-09
  • 【Ruby】Mac gem的一些坑
    前言自上一次升级MacOS系统后出现jekyll无法构建的问题,当时处理半天。谁知道最近又升级了MacOS,荒废博客多时,今天吝啬写了一篇准备发布,构建报错,问题重新。还是记录下,以防下次升级出问题。问题描述安装jekyll静态博客需要在Ruby环境下运行,于是参照
    02-09
  • iOS oc 调用 swift
    如股票oc要调用swift里面的代码 需要包含固定这个头文件项目名称 LiqunSwiftDemo-Swift.h         #ProjectName#-Swift.h固定的写法swift 目的 是取代oc 但是 不会完全取代 只是前端的替换LiqunSwiftDemo-Swift 点进去 可以看到 所有的swift代码 都产生
    02-09
  • objective-c NSTimer 定时器
    -(void)initTimer{//时间间隔NSTimeInterval timeInterval =3.0 ;//定时器repeats 表示是否需要重复,NO为只重复一次NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:timeInterval target:self selector:@selector(mobileAnimation) userInfo:nil
    02-09
  • Objective-C  日记③ 字符串
    Objective-C 日记③ 字符串
    一、创建字符串、类方法   公式创建NSString  +(id) stringWithFormat:(NSString *) format,……;eg:  NSString *height;  height=[NSString stringWithFormat:@"高度是: %d 长度: %d",10,20];得到的字符串:“高度是: 10 长度: 20” 注意:  省
    02-09
  • Objective-C KVC机制
    Objective-C KVC机制http://blog.csdn.net/omegayy/article/details/7381301全部推翻重写一个版本,这是我在公司内做技术分享的文档总结,对结构、条理做了更清晰的调整。 1.    基本概念MODEL主要是英文文档里面经常出现的一些概念,讲解一下,方便英文
    02-09
  • objective-c 加号 减号 - +
    “加号代表static”是错误的说法,可能跟你那样表达的人其实意思是:“前置加号的方法相当于Java 里面的静态方法”。在Oc中,方法分为类方法和实例方法。前置加号(+)的方法为类方法,这类方法是可以直接用类名来调用的,它的作用主要是创建一个实例。有人把
    02-09
  • Objective-C  日记①
    Objective-C 日记①
    1、Xcode的.m扩展名表示文件含有Object-C代码,C以.c文件,C++以.cpp文件2、头文件声明:C使用:#include,O-C使用#import(当然你也可以使用#include) 3、输出方式:  C:printf("",参数);  O-C:NSLog(@"",参数); 4、布尔类型  C:bool 具有true
    02-09
  • ASP.NET MVC 操作AD 获取域服务器当前用户姓
    #region 根据当前登录域账号 获取AD用户姓名和所在OU目录/// summary/// 根据当前登录域账号 获取AD用户姓名和所在OU目录/// /summary/// param name="searchUser"要搜索的当前用户名/param/// param name="paths"out返回该用户所在OU目录/param/// param nam
    02-09
  • swift和OC - 拆分数组 和 拆分字符串
    1. 拆分数组 /// 根据 数组 截取 指定个数返回 多个数组的集合func splitArray( array: [Date], withSubSize subSize: Int) - [[Date]] {//数组将被拆分成指定长度数组的个数let count = array.count% subSize == 0 ? (array.count/ subSize) : (array.count
    02-08
点击排行