static-cast--dynamic-cast--const-cast探讨

上传人:豆浆 文档编号:24901615 上传时间:2017-12-08 格式:PDF 页数:11 大小:245.67KB
返回 下载 相关 举报
static-cast--dynamic-cast--const-cast探讨_第1页
第1页 / 共11页
static-cast--dynamic-cast--const-cast探讨_第2页
第2页 / 共11页
static-cast--dynamic-cast--const-cast探讨_第3页
第3页 / 共11页
static-cast--dynamic-cast--const-cast探讨_第4页
第4页 / 共11页
static-cast--dynamic-cast--const-cast探讨_第5页
第5页 / 共11页
点击查看更多>>
资源描述

《static-cast--dynamic-cast--const-cast探讨》由会员分享,可在线阅读,更多相关《static-cast--dynamic-cast--const-cast探讨(11页珍藏版)》请在金锄头文库上搜索。

1、【 C+专题】 static_cast, dynamic_cast, const_cast 探讨 首先回顾一下 C+类型转换: C+类型转换分为:隐式类型转换和显式类型转换 第 1 部分 . 隐式类型转换 又称为 “标准转换 ”,包括以下几种情况: 1) 算术转换 (Arithmetic conversion) : 在混合类型的 算术表达式 中 , 最宽的数据类型成为目标转换类型。 int ival = 3; double dval = 3.14159; ival + dval;/ival 被提升为 double 类型 2)一种类型表达式赋值给另一种类型的对象:目标类型是被赋值对象的类型 in

2、t *pi = 0; / 0 被转化为 int *类型 ival = dval; / double-int 例外: void 指针赋值给其他指定类型指针时,不存在标准转换,编译出错 3)将一个表达式作为实参传递给函数调用,此时形参和实参类型不一致:目标转换类型为形参的类型 extern double sqrt(double); cout ( expression ) 说明:该运算符把 expression 转换为 type-id 类型,但没有运行时类型检查来保证转换的安全性。 来源:为什么需要 static_cast 强制转换? 情况 1: void 指针 -其他类型指针 情况 2:改变通常的

3、标准转换 情况 3:避免出现可能多种转换的歧义 它主要有如下几种用法: 用于类层次结构中基类和子类之间指针或引用的转换。进行上行转换(把子类的指针或引用转换成基类表示)是安全的;进行下行转换( 把基类指针或引用转换成子类指针或引用 )时,由于没有动态类型检查,所以是不安全的。 用于基本数据类型之间的转换,如把 int 转换成 char, 把 int 转换成 enum。这种转换的安全性也要开发人员来保证。 把 void 指针转换成目标类型的指针 (不安全 !) 把任何类型的表达式转换成 void 类型。 注意: static_cast 不能转换掉 expression 的 const、 voli

4、tale、或者 _unaligned 属性。 dynamic_cast 用法: dynamic_cast ( expression ) 说明:该运算符把 expression 转换成 type-id 类型的对象。 Type-id 必须是类的指针、类的引用或者 void *;如果 type-id 是类指针类型,那么 expression 也必须是一个指针,如果 type-id是一个引用,那么 expression 也必须是一个引用。 来源:为什么需要 dynamic_cast 强制转换? 简单的说,当无法使用 virtual 函数的时候 典型案例: Wicrosoft 公司提供给我们一个类库,其

5、中提供一个类 Employee.以头文件 Eemployee.h 和类库 .lib 分发给用户 显然我们并无法得到类的实现的源代码 /Emplyee.h class Employee public: virtual int salary(); ; class Manager : public Employee public: int salary(); ; class Programmer : public Employee public: int salary(); ; 我们公司在开发的时候建立有如下类 : class MyCompany public: void payroll(Emplo

6、yee *pe); / ; void MyCompany:payroll(Employee *pe) /do something 但是开发到后期,我们希望能增加一个 bonus()的成员函数到 W$公司提供的类层次中。 假设我们知道源代码的情况下,很简单,增加虚函数: /Emplyee.h class Employee public: virtual int salary(); virtual int bonus(); ; class Manager : public Employee public: int salary(); ; class Programmer : public Empl

7、oyee public: int salary(); int bonus(); ; /Emplyee.cpp int Programmer:bonus() / payroll()通过多态来调用 bonus() class MyCompany public: void payroll(Employee *pe); / ; void MyCompany:payroll(Employee *pe) /do something /pe-bonus(); 但是现在情况是,我们并不能修改源代码,怎么办? dynamic_cast 华丽登场了! 在 Employee.h 中增加 bonus()声明,在另一个

8、地方定义此函数,修改调用函数 payroll().重新编译, ok /Emplyee.h class Employee public: virtual int salary(); ; class Manager : public Employee public: int salary(); ; class Programmer : public Employee public: int salary(); int bonus();/直接在这里扩展 ; /somewhere.cpp int Programmer:bonus() /define class MyCompany public: vo

9、id payroll(Employee *pe); / ; void MyCompany:payroll(Employee *pe) Programmer *pm = dynamic_cast(pe); /如果 pe实际指向一个 Programmer 对象 ,dynamic_cast 成功,并且开始指向 Programmer 对象起始处 if(pm) /call Programmer:bonus() /如果 pe 不是实际指向 Programmer 对象, dynamic_cast 失败,并且 pm = 0 else /use Employee member functions dynamic

10、_cast 主要用于类层次间的上行转换和下行转换,还可以用于类之间的交叉转换。 在类层次间进行上行转换时, dynamic_cast 和 static_cast 的效果是一样的;在进行 下行转换时, dynamic_cast 具有类型检查的功能,比 static_cast 更安全。 class Base public: int m_iNum; virtual void foo(); ; class Derived:public Base public: char *m_szName100; ; void func(Base *pb) Derived *pd1 = static_cast(pb)

11、; Derived *pd2 = dynamic_cast(pb); 在上面的代码段中, 如果 pb 实际指向一个 Derived 类型的对象, pd1 和 pd2 是一样的,并 且对这两个指针执行Derived 类型的任何操作都是安全的; 如果 pb 实际指向的是一个 Base 类型的对象,那么 pd1 将是一个指向该对象的指针,对它进行 Derived 类型的操作将是不安全的(如访问 m_szName),而 pd2 将是一个空指针 (即 0,因为 dynamic_cast 失败 )。 另外要注意: Base 要有虚函数,否则会编译出错; static_cast 则没有这个限制。这是由于运行

12、时类型检查需要运行时类型信息,而这个信息存储在类的虚函数表(关于虚函数表的概念,详细可见 )中,只有定义了虚函数的类才有虚函数表,没有定义虚函数的类是没有虚函数表的。 另外, dynamic_cast 还支持交叉转换( cross cast)。如下代码所示。 class Base public: int m_iNum; virtual void f() ; class Derived1 : public Base ; class Derived2 : public Base ; void foo() derived1 *pd1 = new Drived1; pd1-m_iNum = 100;

13、Derived2 *pd2 = static_cast(pd1); /compile error Derived2 *pd2 = dynamic_cast(pd1); /pd2 is NULL delete pd1; 在函数 foo 中,使用 static_cast 进行转换是不被允许的,将在编译时出错;而使用 dynamic_cast 的转换则是允许的,结 果是空指针。 reinpreter_cast 用法: reinpreter_cast (expression) 说明: type-id 必须是一个指针、引用、算术类型、函数指针或者成员指针。它可以把一个指针转换成一个整数,也可以把一个整数

14、转换成一个指针(先把一个指针转换成一个整数,在把该整数转换成原类型的指针,还可以得到原先的指针值)。 该运算符的用法比较多。 const_cast 用法: const_cast (expression) 说明:该运算符用来修改类型的 const 或 volatile 属性。除了 const 或 volatile 修饰之外, type_id 和 expression 的类型是一样的。 常量指针被转化成非常量指针,并且仍然指向原来的对象;常量引用被转换成非常量引用,并且仍然指向原来的对象;常量对象被转换成非常量对象。 Voiatile 和 const 类试。举如下一例: class B public: int m_iNum; void foo() const B b1; b1.m_iNum = 100; /comile error B b2 = const_cast(b1); b2. m_iNum = 200; /fine 上面的代码编译时会报错,因为 b1 是一个常量对象,不能对它进行改变;使用 const_cast 把它转换成一个常量对象,就可以对它的数据成员任意改变。注意: b1 和 b2 是两个不同的对象。

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 商业/管理/HR > 其它文档

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号