2023年8月2日发(作者:)
boost之路⼗六类型转换操作符库由两个⽂件组成。分别在 boost/ ⽂件中定义了 boost::polymorphic_cast 和 boost::polymorphic_downcast 这两个类型转换操作符, 在 boost/lexical_ ⽂件中定义了 boost::lexical_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
}
int main()
{
child *c = new child;
func(c);
father *f = new child;
mother *m = dynamic_cast
}
本例使⽤ dynamic_cast 类型转换操作符两次: 在 func() 函数中,它将指向⽗类的指针转换为指向⼦类的指针。在 main() 中, 它将⼀个指向⽗类的指针转为指向另⼀个⽗类的指针。第⼀个转换称为向下转换(downcast),第⼆个转换称为交叉转换(cross cast)。通过使⽤ sion 的类型转换操作符,可以将向下转换和交叉转换区分开来。#include
struct father
{
virtual ~father() { };
};
struct mother
{
virtual ~mother() { };
};
struct child :
public father,
public mother
{
};
void func(father *f)
{
child *c = boost::polymorphic_downcast
}
int main()
{
child *c = new child;
func(c);
father *f = new child;
mother *m = boost::polymorphic_cast
}
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_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 也不是真正随意使⽤的。sion 还提供了另外⼀种在实践中很有⽤的类型转换操作符。 体会⼀下下⾯的例⼦。#include
#include
#include
int main()
{
std::string s = boost::lexical_cast
std::cout << s << std::endl;
double d = boost::lexical_cast
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
#include
#include
int main()
{
try
{
int i = boost::lexical_cast
std::cout << i << std::endl;
}
catch (boost::bad_lexical_cast &e)
{
std::cerr << () << std::endl;
}
}
本例由于字符串 "abc" 不能转换为 int 类型的数字⽽抛出异常。16.3. cConversion可将⼀种数值类型转换为不同的数值类型。 在C++⾥, 这种转换可以隐式地发⽣,如下⾯例所⽰。#include
int main()
{
int i = 0x10000;
short s = i;
std::cout << s << std::endl;
} 由于从 int 到 short 的类型转换⾃动产⽣,所以本例编译没有错误。 虽然本例可以运⾏,但结果由于依赖具体的编译器实现⽽结果⽆法预期。 数字0x10000对于变量
i
来说太⼤⽽不能存储在 short 类型的变量中。 依据C++标准,这个操作的结果是实现定义的("implementation defined")。 ⽤Visual C++ 2008编译,应⽤程序显⽰的是0。
s 的值当然不同于
i 的值。为避免这种数值转换错误,可以使⽤ boost::numeric_cast 类型转换操作符。#include
#include
int main()
{
try
{
int i = 0x10000;
short s = boost::numeric_cast
std::cout << s << std::endl;
}
catch (boost::numeric::bad_numeric_cast &e)
{
std::cerr << () << std::endl;
}
}
boost::numeric_cast 的⽤法与C++类型转换操作符⾮常相似。 当然需要包含正确的头⽂件;就是 boost/numeric/conversion/。boost::numeric_cast 执⾏与C++相同的隐式转换操作。 但是,boost::numeric_cast 验证了在不改变数值的情况下转换是否能够发⽣。 前⾯给的应⽤例⼦,转换不能发⽣,因⽽由于0x10000太⼤⽽不能存储在 short 类型的变量上,⽽抛出 boost::numeric::bad_numeric_cast 异常。严格来讲,抛出的是 boost::numeric::positive_overflow 类型的异常,这个类型特指所谓的溢出(overflow) - 在此例中是正数。 相应地,还存在着 boost::numeric::negative_overflow 类型的异常,它特指负数的溢出。#include
#include
int main()
{
try
{
int i = -0x10000;
short s = boost::numeric_cast
std::cout << s << std::endl;
}
catch (boost::numeric::negative_overflow &e)
{
std::cerr << () << std::endl;
}
}
cConversion 还定义了其他的异常类型,都继承⾃ boost::numeric::bad_numeric_cast。 因为boost::numeric::bad_numeric_cast 继承⾃ std::bad_cast,所以 catch 处理也可以捕获这个类型的异常。
发布者:admin,转转请注明出处:http://www.yc00.com/news/1690907640a460449.html
评论列表(0条)