-
C++教程之类型转换高级 (Advacned Class Type-casting)
类型转换高级 (Advacned Class Type-casting)
目前为止,我们一直使用传统的类型转换符来进行简单对象的类型转换。例如,要把一个double类型的浮点型数字转换为int 的整型数字,我们是这样做的:int i;
double d;
i = (int) d;
或者
i = int (d);
这样做对基本数据类型时没问题的,因为基本数据类型的转换已经有标准的定义。同样的操作也可以被在类或类的指针上,因此以下例子中的写法也是没有问题的:
// class type-casting #include <iostream.h> class CDummy { int i; }; class CAddition { int x,y; public: CAddition (int a, int b) { x=a; y=b; } int result() { return x+y;} }; int main () { CDummy d; CAddition * padd; padd = (CAddition*) &d; cout << padd->result(); return 0; } |
为了控制这种类之间的转换,ANSI-C++ 标准定义了4种新的类型转换操作符: reinterpret_cast, static_cast, dynamic_cast 和 const_cast。所有这些操作符都是同样的使用格式:
reinterpret_cast <new_type> (expression)
dynamic_cast <new_type> (expression)
static_cast <new_type> (expression)
const_cast <new_type> (expression)
这里new_type 是要转换成的目标类型,expression 是要被转换的内容。为了便于理解,模仿传统转换操作符,它们的含义是这样的:
(new_type) expression
new_type (expression)
reinterpret_cast
reinterpret_cast 可以将一个指针转换为任意其它类型的指针。它也可以用来将一个指针转换为一个整型,或反之亦然。这个操作符可以在互不相关的类之间进行指针转换,操作的结果是简单的将一个指针的二进制数据(binary copy)复制到另一个指针。对指针指向的内容不做任何检查或转换。
如果这种复制发生在一个指针到一个整数之间,则对其内容的解释取决于不同的系统,因此任何实现都是不可移植(non portable)的。一个指针如果被转换为一个能够完全存储它的足够大的整数中,则是可以再被转换回来成为指针的。
例如:
class A {};
class B {};
A * a = new A;
B * b = reinterpret_cast<B*>(a);
reinterpret_cast 对所有指针的处理与传统的类型转换符所作的一模一样。
static_cast
static_cast 可以执行所有能够隐含执行的类型转换,以及它们的反向操作(即使这种方向操作是不允许隐含执行的)。用于类的指针,也就是说,它允许将一个引申类的指针转换为其基类类型(这是可以被隐含执行的有效转换),同时也允许进行相反的转换:将一个基类转换为一个引申类类型。
在后面一种情况中,不会检查被转换的基类是否真正完全是目标类型的。例如下面的代码是合法的:
class Base {};
class Derived: public Base {};
Base * a = new Base;
Derived * b = static_cast(a);
static_cast除了能够对类指针进行操作,还可以被用来进行类中明确定义的转换,以及对基本类型的标准转换:
double d=3.14159265;
int i = static_cast<int>(d);
译者注:如果你对这部分看不太懂,请结合下面的dynamic_cast一起看,也许会帮助理解。
dynamic_cast
dynamic_cast 完全被用来进行指针的操作。它可以用来进行任何可以隐含进行的转换操作以及它们被用于多态类情况下的方向操作。然而与static_cast不同的是, dynamic_cast 会检查后一种情况的操作是否合法,也就是说它会检查类型转换操作是否会返回一个被要求类型的有效的完整的对象。这种检查是在程序运行过程中进行的。如果被转换的指针所指向的对象不是一个被要求类型的有效完整的对象,返回值将会是一个空指针NULL 。
class Base { virtual dummy(){}; }; class Derived : public Base { }; Base* b1 = new Derived; Base* b2 = new Base; Derived* d1 = dynamic_cast(b1); // succeeds
Derived* d2 = dynamic_cast(b2); // fails: returns NULL
如果类型转换被用在引用(reference)类型上,而这个转换不可能进行的话,一个bad_cast 类型的例外(exception)将会被抛出:
class Base { virtual dummy(){}; }; class Derived : public Base { }; Base* b1 = new Derived; Base* b2 = new Base; Derived d1 = dynamic_cast(b1); // succeeds
Derived d2 = dynamic_cast(b2); // fails: exception thrown
const_cast
这种类型转换对常量const 进行设置或取消操作:class C {};
const C * a = new C;
C * b = const_cast<C*> (a);
其他3种cast 操作符都不可以修改一个对象的常量属性(constness)。
typeid
ANSI-C++ 还定义了一个新的操作符叫做 typeid ,它检查一个表达式的类型:typeid (expression)
这个操作符返回一个类型为type_info的常量对象指针,这种类型定义在标准头函数中。这种返回值可以用操作符 == 和 != 来互相进行比较,也可以用来通过name()函数获得一个描述数据类型或类名称的字符串,例如:
// typeid, typeinfo #include <iostream.h> #include <typeinfo> class CDummy { }; int main () { CDummy* a,b; if (typeid(a) != typeid(b)) { cout << "a and b are of different types:\n"; cout << "a is: " << typeid(a).name() << '\n'; cout << "b is: " << typeid(b).name() << '\n'; } return 0; } |
a and b are of different types: a is: class CDummy * b is: class CDummy |
最新更新
nodejs爬虫
Python正则表达式完全指南
爬取豆瓣Top250图书数据
shp 地图文件批量添加字段
爬虫小试牛刀(爬取学校通知公告)
【python基础】函数-初识函数
【python基础】函数-返回值
HTTP请求:requests模块基础使用必知必会
Python初学者友好丨详解参数传递类型
如何有效管理爬虫流量?
2个场景实例讲解GaussDB(DWS)基表统计信息估
常用的 SQL Server 关键字及其含义
动手分析SQL Server中的事务中使用的锁
openGauss内核分析:SQL by pass & 经典执行
一招教你如何高效批量导入与更新数据
天天写SQL,这些神奇的特性你知道吗?
openGauss内核分析:执行计划生成
[IM002]Navicat ODBC驱动器管理器 未发现数据
初入Sql Server 之 存储过程的简单使用
SQL Server -- 解决存储过程传入参数作为s
JavaScript判断两个数组相等的四类方法
js如何操作video标签
React实战--利用甘特图和看板,强化Paas平
【记录】正则替换的偏方
前端下载 Blob 类型整理
抽象语法树AST必知必会
关于JS定时器的整理
JS中使用Promise.all控制所有的异步请求都完
js中字符串的方法
import-local执行流程与node模块路径解析流程