关闭

c++命名类型转换

标签: 命名类型转换
219人阅读 评论(0) 收藏 举报
分类:

C++的4种命名类型转换


格式:cast-name<type>(expression);
其中type是待转换的目标类型,expression是被转换的值;若type是一个引用,则转换后的结果是一个左值。
cast-name是以下4种中的一种:
static_cast, dynamic_cast,const_cast,reinterpret_cast
其中dynamic_cast支持运行时类型识别,以下只介绍前3种。

static_cast

除了涉及low-level const,任何其他定义良好的类型转换都可以使用static_cast。例如,可以将int型操作数转换成double以达到在在语句中使用浮点型进行除法操作的目的。
static_cast的应用场景:
1.当一个较大的数据类型被赋值为一个较小的数据类型。使用该转换后,编译器会关闭警告信息(潜在的精度丢失)
int	i, j;
double d = static_cast<double>(j) / i;
2.编译器不会自动转换时
例如,使用static_cast获得一个void* 类型的指针所指向地址的值
void* p = &d;	//ok:任何非const类型的对象可以用void* 存储
double *dp = static_cast<double*>(p);	//ok:转换void* 回到原始指针类型

const_cast

cosnt_cast只改变操作数的low-level const
const char* pc;
char* p = const_cast<char*>(pc);//ok:但是写p操作未定义
若原类型为非const,使用该转换获得写权限是合法的;否则未定义
const_cast通常只被用来改变一个表达式的常量属性。试图通过其他的转转(非const_cast)改变表达式的常量属性会在编译器出错。同样地,不能用const_cast改变表达式的类型
const char* cp;
char* q = static_cast<char*>(cp);
static_cast<string>(cp);// ok
const_cast<string>(cp);//error:const_cast只改变常量属性
const_cast的应用场景:在重载函数中最常用到

reinterpret_cast

reinterpret_cast 通常对操作数的位模式(bit pattern)重新解读
例如:
int* ip;
char* pc = reinterpret_cast<char*>(ip);
pc所指向的实际对象为int类型,而不是char。任何假使pc所指向的类型是一个char类型的使用都会在运行时出错
例如:
string str(pc);</span></span>
注意:使用pc初始化str是危险的。问题在于类型改变了,编译器假设pc是char*类型,然后使用pc初始化string类型,这对编译器来说是合法的,所以此时编译器不会给出任何警告和报错,然而实际上pc是一个int*。此时初始化是无意义的甚或者比较糟糕。追踪这种问题导致的结果非常困难,尤其是当ip到pc的转换发生在和用pc初始化str不同的文件
警告:
reinterpret_cast是依赖于机器的。想要安全地使用reinterpret_cast需要全面理解以及知道编译器实现它的细节。

dynamic_cast

Run-time identification(RTTI)可以通过两个操作符实现:
1.typeid,返回指定表达式的类型
2.dynamic_cast,安全地将指向基类的指针或引用转换为指向子类的指针或引用
当需要用指向基类的指针或引用来操作子类时,可以选择虚函数实现。当该操作不能定义为虚函数时,可以使用这两个操作符中的一个来实现。当然,使用操作符来实现更以出错:程序员必须知道要转换的类型以及确保转换成功。
警告:
RTTI应当小心使用。尽量使用虚函数而不是直接通过操作符来直接管理类型。

dynamic_cast有以下3中形式:
1.dynamic_cast<type*>(e) 
2.dynamic_cast<type&>(e)
3.dynamic_cast<type&&>(e)
其中type必须是class类型并且通常是有虚函数的类
1中e必须为合法的指针,2中e必须为左值,3中e不能为左值,e可以从目标类型公有继承而来,可以是目标类型的公有基类,或者和目标类型相同。以上情形下转换才会成功;否则,转换回失败。若dynamic_cast转换成某个指针类型失败,结果为0,;若转换为某个引用类型失败,则会抛出一个bad_cast。

pointer_type dynamic_casts
例如:Base作为基类并且至少有一个虚函数,Derived公有继承自Base。bp指向Base,在运行时,可以将bp转换为指向Derived的指针
if(Derived* dp = dynamic_cast<Derived*>(bp))//在条件语句中初始化bp确保bp在if语句外部不可用;如果转换失败,dp也不可访问
{
	//use the Derived object to which dp points
}else{	//bp points at a Base object
	//use the Base object to which bp points
}
注意:
可以使用dynamic_cast对空指针进行转换,转换结果为要转换类型的空指针

reference_type dynamic_casts
由于引用不能为空,所以当转换为引用失败时会抛bad_cast异常(在typeinfo库中定义)
可以使用引用并改写之前的例子
void f(const Base &b)
{
	try{
		const Derived &d = dynamic_cast<const Derived&>(b);
	}catch (bad_cast) {
		//handle the fact that the cast failed
	} 
}


延伸:Old-Style Casts


在早期版本的C++中,显式转换有以下两种形式:
type (expr);	//函数风格的转换
(type) expr; 	//C语言风格的转换
建议:
转换涉及正常的类型检查。因此强烈建议程序员避免转换。此建议尤其对reinterpret_cast适用。这种转换总是有风险的。const_cast在重载函数中很有用,而其他的用法则是一个程序设计的缺陷。关于其他的类型转换,如static_cast和dynamic_cast,不应该频繁使用。每次在写一个转换之前,需要考虑清楚是否可以通过一个不同的方法来达到同样的目的。如果转换在所难免,可以通过限定转换值使用的范围并且记录关于类型的所有假设来使错误发生的概率减小。

依赖于所涉及的类型,旧风格的转换可以实现和const_cast, static_cast, reinterpret_cast同样的效果。当用static_cast或者const_cast合法的时,用旧风格也可以完成和相应的命名转换同样的转换。如果这两种转换都不合法,则旧风格的转换等同于reinterpret_cast. 例如:
char* pc = (char*) ip;	//ip是一个int*
和使用reinterpret_cast有同样的效果。
警告:
旧风格的转换相比命名转换而言不明显。因为很容易被忽略,所以追踪一个不合法的转换非常困难。

Reference:C++ Primer, 5th edition
0
0
查看评论

c++11中四种类型转换

1、  static_cast: 功能:完成编译器认可的隐式类型转换。 格式type1 a; type2 b = staic_cast(a);将type1的类型转化为type2的类型; 使用范围: (1)基本数据类型之间的转换,如int->double; int a = ...
  • bian_qing_quan11
  • bian_qing_quan11
  • 2017-04-26 10:44
  • 970

C++四种类型转换机制

本文主要借鉴自cplusplus中关于类型转换的内容。传统的类型转换主要有以下两种形式:double x = 10.3; int y; y = int (x); // functional notation y = (int) x; // c-like cast notation这种形式...
  • Swartz2015
  • Swartz2015
  • 2017-04-07 21:50
  • 845

C++四大类型转换

C++ 是一门强类型语言(C语言是弱类型语言),不同自定义类型之间的转换必须进行显式转换。C++ 中提供了四种转换操作符来细分显式类型转换。因为是操作符,所以他们不属于任何的namespace,也就不用包含任何头文件就可以使用。static_cast <new_type> (expres...
  • Robin__Chou
  • Robin__Chou
  • 2016-07-19 17:17
  • 991

c++与c#的类型转换

c++与c#的类型转换 分类:cSharp | 标签: c#   system   intptr   char   uint   201...
  • lphbtm
  • lphbtm
  • 2016-12-07 15:55
  • 506

C++ 向上与向下类型转换

一,向上类型转换 把一个指向派生类对象的指针,转换成指向基类对象的指针,称为向上类型转换。向上类型转换是安全的,也不需要进行强制类型转换。因为在派生类对象中,有一部分存储的是基类对象,向上类型转化可以理解为,把指向派生类对象的指针转换成指向派生类对象中包含的基类对象。 class Base{ pri...
  • cloud323
  • cloud323
  • 2017-03-23 13:41
  • 325

【c/c++】类型转换函数(类型转换运算符重载函数)

用转换构造函数可以将一个指定类型的数据转换为类的对象。但是不能反过来将一个类的对象转换为一个其他类型的数据(例如将一个Complex类对象转换成double类型数据)。 C++提供类型转换函数(type conversion function)来解决这个问题。类型转换函数的作用是将一个类的对象转换...
  • lzm18064126848
  • lzm18064126848
  • 2016-01-04 18:09
  • 2795

C++四种类型转换的关键字及其特点

C++四种类型转换的关键字及其特点 原文地址:http://blog.sina.com.cn/s/blog_5a2bbc860101hgho.html C++的四种强制类型转换,所以C++不是类型安全的。 关键字分别为:static_cast , dynamic_cast , const_ca...
  • u010025211
  • u010025211
  • 2015-09-21 15:08
  • 1242

c++默认类型转化

以下代码执行后,val的值是_:unsigned long val = 0; char a = 0x48; char b = 0x52; val = b << 8 | a;正确答案: B A.20992 B.21064 C.72 D.0答案解析: 这里面涉及到了默认类型转换:当...
  • Mimahoo
  • Mimahoo
  • 2016-04-14 08:49
  • 220

C++自动类型转换

自动类型转换:a.构造函数转换  b.运算符转换。 构造函数转换:如果定义一个构造函数,它把另一个类型对象或引用作为它的单个参数,那么这个构造函数允许编译器执行自动类型转换。 class One { public: One() {} }; class Two { public: T...
  • h1023417614
  • h1023417614
  • 2014-01-03 20:14
  • 2628

C/C++的显式类型转换

C/C++的显式类型转换         在C/C++中,我们可以显式地将某个值、变量或对象强制转换成某种特定的类型。 C          C语言中的显示类型转换非常...
  • q5806622
  • q5806622
  • 2015-01-11 16:02
  • 922
    个人资料
    • 访问:3468次
    • 积分:49
    • 等级:
    • 排名:千里之外
    • 原创:0篇
    • 转载:2篇
    • 译文:1篇
    • 评论:0条
    文章分类
    文章存档