类型转换操作符:static_cast, dynamic_cast, const_cast, reinterpret_cast

news/2024/6/29 11:50:30 标签: class, 语言, 编译器, c, delete, ui
cle class="tags" href="/tags/CLASS.html" title=class>class="baidu_pl">
cle_content" class="tags" href="/tags/CLASS.html" title=class>class="article_content clearfix">
content_views" class="tags" href="/tags/CLASS.html" title=class>class="htmledit_views">

color:rgb(51,51,51)">呵呵࿰c;今天来好好看看着几个转换操作符的用法。以前老是看着眼熟࿰c;但是用着手生。今天决定搞定这些个东西。

color:rgb(51,51,51)">在Cclass="tags" href="/tags/YuYan.html" title=语言>语言中类型转换有几种方式:

color:rgb(51,51,51)">1.      (expression). 在表达式外边加括号࿰c;由class="tags" href="/tags/BianYiQi.html" title=编译器>编译器来决定怎么改变。

color:rgb(51,51,51)">2.      new_type(expression). 强制类型括号住表达式。

color:rgb(51,51,51)">3.      (new_type)expression. 括号住强制类型。

color:rgb(51,51,51)">4.      Cclass="tags" href="/tags/YuYan.html" title=语言>语言允许的内置转换。

color:rgb(51,51,51)">这些转换非常高效࿰c;我非常喜欢使用。特别是在指针转换和数值转换时用到的非常多。只要编写程序的人知道自己要做什么转换࿰c;并知道应该怎样转换的话࿰c;我认为上边的转换方式非常之好。但是没有清楚的了解每个转换的细节的话࿰c;就有可能出现问题࿰c;比如指针指向不应该指向的区域:出现野指针或者指向位置错误(主要是对内存结构不了解)࿰c;或者计算数值被截去等问题发生。

color:rgb(51,51,51)">C++程序兼容Cclass="tags" href="/tags/YuYan.html" title=语言>语言的转化࿰c;但是针对面向对象class="tags" href="/tags/YuYan.html" title=语言>语言的特性࿰c;设计了以下几个类型转换操作符。他们的出现是为了Cclass="tags" href="/tags/YuYan.html" title=语言>语言类型转换中语义模糊和固有的危险陷阱࿰c;因为Cclass="tags" href="/tags/YuYan.html" title=语言>语言不去判断所要操作的类型转换是否合理。

color:rgb(51,51,51)">static_cast:用于非多态类型的转换。

color:rgb(51,51,51)">dynamic_cast:用于多态类型的转换。

color:rgb(51,51,51)">const_cast:用来消除const, volatile, __unaligned属性的转换。

color:rgb(51,51,51)">reinterpret_cast:用于空间的重新解释。

color:rgb(51,51,51)">还有一个在VS2005中出现的类型转换关键字safe_cast.#2

color:rgb(51,51,51)"> 

color:rgb(51,51,51)">static_cast:

color:rgb(51,51,51)">static_cast<type_id>(expression)

color:rgb(51,51,51)">这个关键字可以用来将一个指针转换为父类的指针也可以转换为子类的指针或者基本的类型转换。但是这种转换是强制的࿰c;并没有任何运行时类型检查来保证转换的正确性࿰c;所以编写代码的人需要明白自己所进行的转换是否合理。

color:rgb(51,51,51)">//基本类型的转换

color:rgb(51,51,51)">enum e { A = 1, B, C };

color:rgb(51,51,51)">double d = 12.25;

color:rgb(51,51,51)">unsigned int ui = 25;

color:rgb(51,51,51)">char c = static_cast<char>(ui);

color:rgb(51,51,51)">int i = static_cast<int>(d);

color:rgb(51,51,51)">int j = static_cast<int>(B);

color:rgb(51,51,51)">//父类子类转换

color:rgb(51,51,51)">class="tags" href="/tags/CLASS.html" title=class>class F                  //father

color:rgb(51,51,51)">{

color:rgb(51,51,51)">public:

color:rgb(51,51,51)">    int _father;

color:rgb(51,51,51)">};

color:rgb(51,51,51)">class="tags" href="/tags/CLASS.html" title=class>class S : public F       //son

color:rgb(51,51,51)">{

color:rgb(51,51,51)">public:

color:rgb(51,51,51)">    _son;

color:rgb(51,51,51)">};

color:rgb(51,51,51)">F *pFather = new F();

color:rgb(51,51,51)">S *pSon = new S();

color:rgb(51,51,51)">F *pF;

color:rgb(51,51,51)">S *pS;

color:rgb(51,51,51)">pF = static_cast<F *>(pSon);    //将子类指针转换为父类指针࿰c;OK

color:rgb(51,51,51)">pS = static_cast<S *>(pFather); //将父类指针转换为子类指针࿰c;错误

color:rgb(51,51,51)">第二个错误的转换不是说class="tags" href="/tags/BianYiQi.html" title=编译器>编译器编译不过去࿰c;而是运行时会出现错误。

color:rgb(51,51,51)">原因如下:假设pF指向了pSon的位置࿰c;它可以访问_father࿰c;它找不到_son࿰c;这样没有问题。但是pS指向了pFather的位置࿰c;它访问_father没有问题࿰c;但是访问_son时就会产生错误࿰c;因为pFather根本没有_son这个变量。

color:rgb(51,51,51)">下面是将父类转换为子类指针时࿰c;static_cast和dymanic_cast两者不同的表现:

color:rgb(51,51,51)">class="tags" href="/tags/CLASS.html" title=class>class F

color:rgb(51,51,51)">{

color:rgb(51,51,51)">public:

color:rgb(51,51,51)">    virtual void speak(){};

color:rgb(51,51,51)">    int i;

color:rgb(51,51,51)">};

color:rgb(51,51,51)"> 

color:rgb(51,51,51)">class="tags" href="/tags/CLASS.html" title=class>class S : public F

color:rgb(51,51,51)">{

color:rgb(51,51,51)">public:

color:rgb(51,51,51)">    void speak()

color:rgb(51,51,51)">    {

color:rgb(51,51,51)">       cout << "S = " << _s << endl;

color:rgb(51,51,51)">    }

color:rgb(51,51,51)">    double _s;

color:rgb(51,51,51)">};

color:rgb(51,51,51)">F *pF = new F();

color:rgb(51,51,51)">S *pS = static_cast<S*>(pF);

color:rgb(51,51,51)">pS->speak();

color:rgb(51,51,51)">S1 *pDS = dynamic_cast<S*>(pF);

color:rgb(51,51,51)">pDS->speak();

color:rgb(51,51,51)">静态的转换编译不显示警告࿰c;运行结果不输出(调用F的speak函数)。动态的转换编译显示可能出现不可预期的结果࿰c;运行时崩溃。(VS2005时࿰c;返回空指针࿰c;但是不会崩溃。我认为要是按照C++的特性还是崩溃比较好一点࿰c;让程序员容易理解这么做是错误的。)

color:rgb(51,51,51)"> 

color:rgb(51,51,51)">dynamic_cast:

color:rgb(51,51,51)">dynamic_cast<type_id>(expression)

color:rgb(51,51,51)">本关键字主要处理多态的类型转换࿰c;type_id要么是指针类型࿰c;要么是引用类型要么是void*。当type_id为指针和void*时࿰c;expression必须是type_id类型的指针࿰c;当type_id为引用时࿰c;expression也必须是type_id类型的引用。#1

color:rgb(51,51,51)"> 

color:rgb(51,51,51)">1.最常用的用法就是将子类指针转换为父类指针。(不举例)

color:rgb(51,51,51)">2.当type_id为void*时࿰c;指针指向整个对象的空间。

color:rgb(51,51,51)">Class A;

color:rgb(51,51,51)">A *pA = new A();

color:rgb(51,51,51)">void *p = dynamic_cast<void*>(pA);

color:rgb(51,51,51)">但是type_id不为void*时࿰c;计算机就要在运行时检查是否能够转换。

color:rgb(51,51,51)">3.跳级转换。

color:rgb(51,51,51)">class="tags" href="/tags/CLASS.html" title=class>class A{};

color:rgb(51,51,51)">class="tags" href="/tags/CLASS.html" title=class>class B : public A{};

color:rgb(51,51,51)">class="tags" href="/tags/CLASS.html" title=class>class C : public B{};

color:rgb(51,51,51)">    A *pA;

color:rgb(51,51,51)">    B *pB;

color:rgb(51,51,51)">    C *pC = new C();

color:rgb(51,51,51)">    pB = dynamic_cast<B*>(pC);  //逐级转换OK

color:rgb(51,51,51)">    pA = dynamic_cast<A*>(pB);  //逐级转换OK

color:rgb(51,51,51)">    或者

color:rgb(51,51,51)">    pA = dynamic_cast<A*>(pC);  //跳级转换OK

color:rgb(51,51,51)">    delete pC;

color:rgb(51,51,51)">以下情况跳级转换不可以:

color:rgb(51,51,51)">

color:rgb(51,51,51)">class="tags" href="/tags/CLASS.html" title=class>class A{};

color:rgb(51,51,51)">class="tags" href="/tags/CLASS.html" title=class>class B : public A{};

color:rgb(51,51,51)">class="tags" href="/tags/CLASS.html" title=class>class C : public A{};

color:rgb(51,51,51)">class="tags" href="/tags/CLASS.html" title=class>class D : public B, public C{};

color:rgb(51,51,51)">    A *pA;

color:rgb(51,51,51)">    D *pD = new D();

color:rgb(51,51,51)">    pA = dynamic_cast<A*>(pB);  //出现错误࿰c;是不行的࿰c;原因大家都清楚。

color:rgb(51,51,51)"> 

color:rgb(51,51,51)">

color:rgb(51,51,51)">class="tags" href="/tags/CLASS.html" title=class>class A{};

color:rgb(51,51,51)">class="tags" href="/tags/CLASS.html" title=class>class B : public A{};

color:rgb(51,51,51)">class="tags" href="/tags/CLASS.html" title=class>class C : public A{};

color:rgb(51,51,51)">class="tags" href="/tags/CLASS.html" title=class>class D : public B{};

color:rgb(51,51,51)">class="tags" href="/tags/CLASS.html" title=class>class E : public C, public D{};

color:rgb(51,51,51)">    A *pA;

color:rgb(51,51,51)">    B *pB;

color:rgb(51,51,51)">    E *pE = new E();

color:rgb(51,51,51)">    pB = dynamic_cast<B*>(pE);

color:rgb(51,51,51)">    pA = dynamic_cast<A*>(pB);  //可以

color:rgb(51,51,51)">    pA = dynamic_cast<A*>(pE);  //不可以࿰c;原因是很简单的。

color:rgb(51,51,51)">    delete pE;

color:rgb(51,51,51)">4.两个不相干的类之间转换。

color:rgb(51,51,51)">class="tags" href="/tags/CLASS.html" title=class>class A {};

color:rgb(51,51,51)">class="tags" href="/tags/CLASS.html" title=class>class B {};

color:rgb(51,51,51)">    A* pa = new A;

color:rgb(51,51,51)">    B* pb = dynamic_cast<B*>(pa);   // 不可以࿰c;没有相互转换的基础

color:rgb(51,51,51)">但是reinterpret_cast可以转换࿰c;可以参考reinterpret_cast

color:rgb(51,51,51)"> 

color:rgb(51,51,51)"> 

color:rgb(51,51,51)">const_cast:

color:rgb(51,51,51)">const_cast<type_id>(expression)

color:rgb(51,51,51)">这个关键字消除了几个关键字的作用const, volatile,和__unaligned的作用。const经常使用。MSDN有const的例子照抄过来。

color:rgb(51,51,51)">class="tags" href="/tags/CLASS.html" title=class>class CCTest {

color:rgb(51,51,51)">public:

color:rgb(51,51,51)">   void setNumber( int );

color:rgb(51,51,51)">   void printNumber() const;

color:rgb(51,51,51)">private:

color:rgb(51,51,51)">   int number;

color:rgb(51,51,51)">};

color:rgb(51,51,51)">void CCTest::setNumber( int num ) { number = num; }

color:rgb(51,51,51)">void CCTest::printNumber() const {

color:rgb(51,51,51)">   cout << "/nBefore: " << number;

color:rgb(51,51,51)">   const_cast< CCTest * >( this )->number--;//这里消除了const的作用

color:rgb(51,51,51)">   cout << "/nAfter: " << number;

color:rgb(51,51,51)">}

color:rgb(51,51,51)">int main() {

color:rgb(51,51,51)">   CCTest X;

color:rgb(51,51,51)">   X.setNumber( 8 );

color:rgb(51,51,51)">   X.printNumber();

color:rgb(51,51,51)">}

color:rgb(51,51,51)"> 

color:rgb(51,51,51)">reinterpret_cast:

color:rgb(51,51,51)">reinterpret_cast

color:rgb(51,51,51)">这个关键字比较“强悍”࿰c;随意转换类型。但是转换错误࿰c;就是你的不对了。呵呵࿰c;我的原则两个字:“慎用”。

color:rgb(51,51,51)">这个关键字可以在任何类型的指针之间转换。

color:rgb(51,51,51)">不可以替代const_cast。

color:rgb(51,51,51)">不提供安全转换。

color:rgb(51,51,51)">MSDN的例子显示出来它的强悍࿰c;也显示出了他的脆弱。只要你一个不小心就会乱用。

color:rgb(51,51,51)">#include <iostream>

color:rgb(51,51,51)"> 

color:rgb(51,51,51)">// Returns a hash code based on an address

color:rgb(51,51,51)">unsigned short Hash( void *p ) {

color:rgb(51,51,51)">   unsigned int val = reinterpret_cast<unsigned int>( p );

color:rgb(51,51,51)">   return ( unsigned short )( val ^ (val >> 16));

color:rgb(51,51,51)">}

color:rgb(51,51,51)"> 

color:rgb(51,51,51)">using namespace std;

color:rgb(51,51,51)">int main() {

color:rgb(51,51,51)">   int a[20];

color:rgb(51,51,51)">   for ( int i = 0; i < 20; i++ )

color:rgb(51,51,51)">      cout << Hash( a + i ) << endl;

color:rgb(51,51,51)">}

cle>

http://www.niftyadmin.cn/n/790742.html

相关文章

C++中Static作用和使用方法

1、什么是static? static 是C中很常用的修饰符&#xff0c;它被用来控制变量的存储方式和可见性。 2、为什么要引入static? 函数内部定义的变量&#xff0c;在程序执行到它的定义处时&#xff0c;编译器为它在栈上分配空间&#xff0c;大家知道&#xff0c;函数…

Mean Shift和CamShift算法

Mean Shift和CamShift算法 转自 一位前辈联系方式&#xff1a; QQ: 7578420 Email: shichongdong80gmail.com/*****************************************************************************/CamShift算法&#xff0c;即"Continuously Apative Mean-Shift"算法&am…

挖雷游戏的概率

编程之美最后一题“挖雷游戏的概率”没附答案, 有一则脚注云“此题适合MATLAB用户解答”, 颇感有趣. 题目说, 一局1616的扫雷游戏刚开始, 只翻开了两格, 分别显示数字1和2, 如下图所示(只画出了35的局部示意图). 设地雷总数从10逐渐增加到240, 请分别作出图中A, B, C三处为地雷…

如何证明一个数能否被7整除的判定方法

如题&#xff0c;一个数能否被7整除的判定方法是如下的&#xff1a;例如&#xff0c;求344617能否被7整除把617-344273&#xff0c;273能被7整除&#xff0c;所以344617能被7整除又如&#xff0c;求4241468能否被7整除把468-2414231能被7整除&#xff0c;所以4241468能被7整除怎…

STL中的typename与class关键字

在泛型编程的形参表中&#xff0c;关键字typename和class具有相同的含义&#xff0c;可以相互使用&#xff0c;两个关键字都可以在同一模板形参表中使用&#xff1a; 1. typename用在模板定义里&#xff0c;标明其后的模板参数是类型参数。 [html] view plaincopy templat…

placement new 讲解

placement new 是重载operator new的一个标准、全局的版本&#xff0c;它不能被自定义的版本代替&#xff08;不像普通的operator new和operator delete能够被替换成用户自定义的版本&#xff09;。placement new的作用就是&#xff1a;创建对象(调用该类的构造函数)但是不分配…

C++ explicit关键字应用于构造函数

C explicit关键字主要是用来对构造函数进行修饰&#xff0c;来表明这一构造函数是显示的。那么在这里大家就一起来看看其正确的使用方法吧。 C编程语言可以被看做是C语言的一个升级版本&#xff0c;其中有很多应用方式与C语言相似&#xff0c;但同时又比C语言功能更加强大&…

C++里的静态成员函数不能用const的原因

static在c中的第五种含义&#xff1a;用static修饰不访问非静态数据成员的类成员函数。这意味着一个静态成员函数只能访问它的参数、类的静态数据成员和全局变量。不能用const的原因&#xff1a; 这是C的规则&#xff0c;const修饰符用于表示函数不能修改成员变量的值&#xff…