C++ Boost Conversion超详细讲解
目录
- 一、说明
- 二、示例和代码
- 三、更多示例代码
一、说明
Boost.Conversion 在头文件 boost/cast.hpp 中定义了转换运算符 boost::polymorphic_cast 和 boost::polymorphic_downcast。它们旨在更精确地处理类型转换——通常使用 dynamic_cast 完成。
库由两个文件组成。分别在boost/cast.hpp
文件中定义了boost::polymorphic_cast
和boost::polymorphic_downcast
这两个类型转换操作符, 在boost/lexical_cast.hpp
文件中定义了boost::lexiphpcal_cast
。
二、示例和代码
boost::polymorphic_cast
和boost::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 sBCxfslsI{ virtual ~father() { }; }; struct mother { virtual ~mother() 开发者_JAVA教程{ }; }; 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_downcjavascriptast
类型转换操作符只能用于向下转换。 它内部使用 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_downcast
和boost::polymorphic_cast
只在指针必须转换的时候使用;否则,必须使用dynamic_cast
执行转换。 由于boost::polymorphic_downcast
是基于static_cast
,所以它不能够,比如说,将父类对象转换为子类对象。 如果转换的类型不是指针,则使用boost::polymorphic_cast
执行类型转换也没有什么意义,而在这种情况下使用dynamic_cast
还会抛出一个std::bad_cast
异常。
虽然所有的类型转换都可用dynamic_cast
实现,可boost::polymorphic_downcast
和boost::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_cas编程客栈t:在 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 使用 dynamicjavascript_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内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!
精彩评论