C++ Boost Conversion超详细讲解

目录
  • 一、说明
  • 二、示例和代码
  • 三、更多示例代码

一、说明

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 类型的异常。

到此这篇关于C++ Boost Conversion超详细讲解的文章就介绍到这了,更多相关C++ Boost Conversion内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C++ Boost Archive超详细讲解

    目录 一.说明 二.关于Archive库 一.说明 对Boost.Serialization库的应用,存在如下内容: Archive Pointers and References Serialization of Class Hierarchy Objects Wrapper Functions for Optimization Boost.Serialization 库可以将 C++ 程序中的对象转换为可以保存和加载以恢复对象的字节序列.有不同的数据格式可用于定义生成字节序列的规则. Boo

  • C++ Boost Accumulators累加器详细讲解

    Boost.Accumulators Boost.Accumulators 提供了处理样本的类.例如,您可以找到最大或最小的样本,或者计算所有样本的总和.虽然标准库支持其中一些操作,但 Boost.Accumulators 还支持统计计算,例如均值和标准差. 该库称为 Boost.Accumulators,因为累加器是一个基本概念.累加器是一个容器,每次插入一个值时都会计算出一个新的结果.该值不一定存储在累加器中.相反,累加器在输入新值时不断更新中间结果. Boost.Accumulators

  • C++ Boost ProgramOptions超详细讲解

    目录 一.说明 二.示例Boost.ProgramOptions 一.说明 Boost.ProgramOptions Boost.ProgramOptions 是一个可以轻松解析命令行选项的库,例如,控制台应用程序.如果您使用图形用户界面开发应用程序,命令行选项通常并不重要. 要使用 Boost.ProgramOptions 解析命令行选项,需要以下三个步骤: 定义命令行选项.您给它们命名并指定哪些可以设置为一个值.如果命令行选项被解析为键/值对,您还可以设置值的类型——例如,它是字符串还是数字

  • C++ Boost Exception超详细讲解

    Boost.Exception 库提供了一种新的异常类型 boost::exception,它允许您在抛出异常后将数据添加到异常中.此类型在 boost/exception/exception.hpp 中定义.由于 Boost.Exception 将其类和函数分布在多个头文件中,以下示例访问主头文件 boost/exception/all.hpp 以避免一个接一个地包含头文件. Boost.Exception 支持 C++11 标准的机制,该机制将异常从一个线程传输到另一个线程. boost::

  • C++ Boost log日志库超详细讲解

    目录 一.说明 二.库Boost.Log 一.说明 应用程序库是指通常专门用于独立应用程序开发而不用于库开发的库. Boost.Log 是一个日志库. Boost.ProgramOptions 是一个用于定义和解析命令行选项的库. Boost.Serialization 允许您序列化对象,例如,将它们保存到文件或从文件加载它们. Boost.Uuid 支持使用 UUID. 具体内容 62. Boost.Log 63. Boost.ProgramOptions 64. Boost.Serializ

  • C++ Boost Uuid超详细讲解

    目录 一.说明 二.Boost.Uuid库示例和代码 一.说明 Boost.Uuid 为 UUID 提供生成器. UUID 是不依赖于中央协调实例的通用唯一标识符.例如,没有数据库存储所有生成的 UUID,可以检查这些 UUID 是否使用了新的 UUID. UUID 由必须唯一标识组件的分布式系统使用.例如,Microsoft 使用 UUID 来识别 COM 世界中的接口.对于为 COM 开发的新接口,可以轻松分配唯一标识符. UUID 是 128 位数字.存在多种生成 UUID 的方法.例如,

  • C++ Boost Random随机函数详解

    目录 一.说明 二.示例代码 一.说明 Boost.Random 库提供了许多随机数生成器,可让您决定应如何生成随机数.在 C++ 中,始终可以使用来自 cstdlib 的 std::rand() 生成随机数.但是,使用 std::rand() 生成随机数的方式取决于标准库的实现方式. 当包含头文件 boost/random.hpp 时,您可以使用 Boost.Random 中的所有随机数生成器和其他类和函数. 该库的大部分已添加到 C++11 的标准库中.如果您的开发环境支持 C++11,您可

  • C++ Boost System超详细讲解

    目录 一.说明 二.关于 Boost.System库 一.说明 以下库支持错误处理. Boost.System 提供类来描述和识别错误.自 C++11 以来,这些类已成为标准库的一部分. Boost.Exception 使得在抛出异常后附加数据成为可能. 二.关于 Boost.System库 Boost.System Boost.System 是一个库,本质上定义了四个类来识别错误.所有四个类都已添加到 C++11 的标准库中.如果您的开发环境支持 C++11,则无需使用 Boost.Syste

  • C++ Boost Conversion超详细讲解

    目录 一.说明 二.示例和代码 三.更多示例代码 一.说明 Boost.Conversion 在头文件 boost/cast.hpp 中定义了转换运算符 boost::polymorphic_cast 和 boost::polymorphic_downcast.它们旨在更精确地处理类型转换——通常使用 dynamic_cast 完成. 库由两个文件组成.分别在boost/cast.hpp文件中定义了boost::polymorphic_cast和boost::polymorphic_downca

  • C++ Boost Lockfree超详细讲解使用方法

    目录 一.说明 二.示例和代码 Boost.Lockfree 一.说明 Boost.Lockfree 提供线程安全和无锁容器.可以从多个线程访问此库中的容器,而无需同步访问. 在 1.56.0 版本中,Boost.Lockfree 只提供了两个容器:boost::lockfree::queue 类型的队列和 boost::lockfree::stack 类型的栈.对于队列,可以使用第二个实现:boost::lockfree::spsc_queue.此类针对只有一个线程写入队列和只有一个线程从队列

  • C++ Boost ScopeExit超详细讲解

    目录 一.提要 二.退出作用域(Boost.ScopeExit) 2.1 范例1.UsingBOOST_SCOPE_EXIT 2.2 示例2.Boost.ScopeExit和C++11的lambda函数 2.3 示例3.特点BOOST_SCOPE_EXIT 三.练习 一.提要 资源有很多种,每种都封装一套,还是挺繁琐的!对于比较少使用或者一个程序很可能只会用一次的资源,我们不想封装,在这种情况下用Boost.ScopeExit. 二.退出作用域(Boost.ScopeExit) 库 Boost.

  • C++ Boost Utility超详细讲解

    目录 一.说明 二.Boost.Utility库示例和代码 一.说明 Boost.Utility 库是杂项.有用的类和函数的集合,它们太小而无法在独立库中维护.虽然实用程序很小并且可以快速学习,但它们完全无关.与其他章节中的示例不同,此处的代码示例不是相互构建的,因为它们是独立的实用程序. 虽然大多数实用程序都在 boost/utility.hpp 中定义,但有些实用程序有自己的头文件.以下示例包括所介绍的实用程序的相应头文件. 二.Boost.Utility库示例和代码 示例 69.1.使用

  • C++ Boost Assign超详细讲解

    目录 说明 Exercise 说明 Boost.Assign Boost.Assign 库提供了帮助函数来初始化容器或向容器添加元素.如果需要将许多元素存储在一个容器中,这些函数尤其有用.多亏了 Boost.Assign 提供的函数,您不需要重复调​​用像 push_back() 这样的成员函数来将元素一个一个地插入到容器中. 如果您使用支持 C++11 的开发环境,则可以从初始化列表中获益.通常您可以将任意数量的值传递给构造函数来初始化容器.多亏了初始化列表,你不必依赖 C++11 的 Boo

  • C++ Boost Format超详细讲解

    Boost.Format Boost.Format 提供了函数 std::printf() 的替代品. std::printf() 源自 C 标准并允许格式化数据输出.但是,它既不是类型安全的,也不是可扩展的. Boost.Format 提供了一种类型安全且可扩展的替代方案. Boost.Format 提供了一个名为 boost::format 的类,该类在 boost/format.hpp 中定义.与 std::printf() 类似,将包含用于控制格式的特殊字符的字符串传递给 boost::

随机推荐