c++ 四种强制类型转换

const_cast:
  1 #include <iostream>
  2 using namespace std;
  3
  4 int main(){
  5     int k=20;
  6     int const * i=&k;
  7     int* j=const_cast<int*>(i);
  8     *j=40;
  9     cout<<*j<<endl;
 10 //  *i=10;
 11     cout<<*i<<endl;
 12 }  
输出:40 40(有换行)
这里const_cast不能是int型,看编译报错:
typechage.cpp:8: error: invalid use of const_cast with type ‘int’, which is not a pointer, reference, nor a pointer-to-data-member type
显然,const_cast必须是指针,引用,后者可以指向数据成员的类型。
该运算符用来修改类型的const或volatile属性。除了const 或volatile修饰之外, type_id和expression的类型是一样的。

网上有的代码是错的,比如:
class B{

public:

int m_iNum;

}

void foo(){

const B b1;

b1.m_iNum = 100; //comile error

B b2 = const_cast<B>(b1);

b2. m_iNum = 200; //fine
}

至少有三个错误:

1,缺封号;

2,const 对象没有初始化

3,const_cast 也不对


reinterpret_cast:

int main(){
    int k=20;
    int* i=&k;
    int j=reinterpret_cast<int>(i);
    cout<<j<<endl;
}
地址转成int。

type-id必须是一个指针、引用、算术类型、函数指针或者成员指针。它可以把一个指针转换成一个整数,也可以把一个整数转换成一个指针(先把一 个指针转换成一个整数,在把该整数转换成原类型的指针,还可以得到原先的指针值)。


static_cast

用法:static_cast < type-id > ( expression )

该运算符把expression转换为type-id类型,但没有运行时类型检查来保证转换的安全性。它主要有如下几种用法:
用于类层次 结构中基类和子类之间指针或引用的转换。进行上行转换(把子类的指针或引用转换成基类表示)是安全的;进行下行转换(把基类指针或引用转换成子类表示) 时,由于没有动态类型检查,所以是不安全的。
用于基本数据类型之间的转换,如把int转换成char,把int转换成enum。这种转换的安全性 也要开发人员来保证。
把空指针转换成目标类型的空指针。
把任何类型的表达式转换成void类型。
注意:static_cast不 能转换掉expression的const、volitale、或者__unaligned属性。
#include <iostream>

using namespace std;

class Base{
    public:
        Base(int i):data(i){
            cout<<"Base constructor"<<endl;
        }
        Base(const Base& b):data(b.data){           
            cout<<"base copy constructor"<<endl;
        }
        int get_data() const{
            return data;
        }
        void set_data(int i){
            data=i;
        }

        /*operator int (){
            return data;
        }
        */
    private:
        int data;
};

class Dereid:public Base{
    public:
    Dereid(int j):Base(5),data(j){
        cout<<"Dereid constructor"<<endl;
    }
    Dereid(const Dereid& d):Base(5),data(d.data){
        cout<<"dereid copy constructor"<<endl;
    }
    int get_data() const{
            return data;
    }
    private:
    int data;
};

int main(){
    Base b(100);
    Dereid d(50);
    //b.set_data(5);
    Base ba=static_cast<Base>(d);

    cout<<ba.get_data()<<endl;
    cout<<d.get_data()<<endl;

    Dereid* de=static_cast<Dereid*>(&b);
    cout<<de->get_data()<<endl;
}


这里Dereid* de=static_cast<Dereid*>(&b);换成:

Dereid de=static_cast<Dereid>(b);是不对的,报错如下:

typechage.cpp: In function ‘int main()’:
typechage.cpp:51: error: no matching function for call to ‘Dereid::Dereid(Base&)’
typechage.cpp:32: note: candidates are: Dereid::Dereid(const Dereid&)
typechage.cpp:29: note:                 Dereid::Dereid(int)

个人认为:可能static_cast只是以base为参数,构造一个dereid,没有合理的构造参数,所以出错。但是换成指针,就没有这一构造 错误了。

最后一行输出是无意义的。


dynamic_cast:

(1)其他三种都是编译时完成的,dynamic_cast是运行时处理的,运行时要进行类型检查。

(2)不能用于内置的基本数据类型的强制转换。

(3)dynamic_cast转换如果成功的话返回的是指向类的指针或引用,转换失败的话则会返回NULL。

(4)使用dynamic_cast进行转换的,基类中一定要有虚函数,否则编译 不通过。

        B中需要检测有虚函数的原因:类中存在虚函数,就说明它有想要让基类指针或引用指向派生类对象的情况,此 时转换才有意义。

        这是由于运行时类型检查需要运行时类型信息,而这个信息存储在类的虚函数表(关于虚函数表的概念,详细可 见<Inside c++ object model>)中,

        只有定义了虚函数的类才有虚函数表。

 (5)在类的转 换时,在类层次间进行上行转换时,dynamic_cast和static_cast的效果是一样的。在进 行下行转换时,dynamic_cast具有类型检查的功能,比               static_cast更安全。向上转换即为指向子类对象的向下转换,即将父类指针转化子类指针。向下转换的成功与否还与将要转换的类型有关,即要转换的 指针指向的对象的实际类型与转换以后的对象类型一定要相同,否则转换失败。

参考例子:

#include<iostream>
#include<cstring>
using namespace std;
class A
{
   public:
   virtual void f()
   {
       cout<<"hello"<<endl;
   };
};
 
class B:public A
{
    public:
    void f()
    {
        cout<<"hello2"<<endl;
    };
 
};
 
class C
{
  void pp()
  {
      return;
  }
};

int main()
{
    A* a1=new B;//a1是A类型的指针指向一个B类型的对象
    A* a2=new A;//a2是A类型的指针指向一个A类型的对象
    B* b;
    C* c;
    b=dynamic_cast<B*>(a1);//结果为not null,向下转换成功,a1之前指向的就是B类型的对象,所以可以转换成B类型的指针。
    if(b==NULL)
    {
        cout<<"null"<<endl;
    }
    else
    {
        cout<<"not null"<<endl;
    }
    b=dynamic_cast<B*>(a2);//结果为null,向下转换失败
    if(b==NULL)
    {
        cout<<"null"<<endl;
    }
    else
    {
        cout<<"not null"<<endl;
    }
    c=dynamic_cast<C*>(a1);//结果为null,向下转换失败
    if(c==NULL)
    {
        cout<<"null"<<endl;
    }
    else
    {
        cout<<"not null"<<endl;
    }
    delete(a1);
    delete(a2);
    return 0;
}



还是上上段代码,这样使用:

    Base* bas=new Base(600);
    Dereid* de=dynamic_cast<Dereid*>(bas);
    if(de==NULL){
        cout<<"null"<<endl;
    }

没有虚函数:

typechage.cpp:52: error: cannot dynamic_cast ‘bas’ (of type ‘class Base*’) to type ‘class Dereid*’ (source type is not polymorphic)


加上虚函数,这样使用的话:

    Base* bas=new Base(600);
    Dereid* de=dynamic_cast<Dereid*>(&b);
    if(de==NULL){
        cout<<"null"<<endl;
    }

仍然有误:

typechage.cpp:52: warning: dynamic_cast of ‘Base b’ to ‘class Dereid*’ can never succeed

http://blog.163.com/zmhot88@126/blog/static/169846647201152442439896/



C++的四种强制类型转换,所以C++不是类型安全的。分别为:static_cast , dynamic_cast , const_cast , reinterpret_cast
为什么使用C风格的强制转换可以把想要的任何东西转换成合乎心意的类型。那为什么还需要一个新的C++类型的强制转换呢?
新类型的强制转换可以提供更好的控制强制转换过程,允许控制各种不同种类的强制转换。C++中风格是static_cast<type>(content)。C++风格的强制转换其他的好处是,它们能更清晰的表明它们要干什么。程序员只要扫一眼这样的代码,就能立即知道一个强制转换的目的。
四种转换的区别:
static_cast:可以实现C++中内置基本数据类型之间的相互转换。

复制代码 代码如下:

int c=static_cast<int>(7.987);

如果涉及到类的话,static_cast只能在有 相互联系的类型中进行相互转换, 不一定包含虚函数
复制代码 代码如下:

class A
{};
class B:public A
{};
class C
{};

int main()
{
    A* a=new A;
    B* b;
    C* c;
    b=static_cast<B>(a);  // 编译不会报错, B类继承A类
    c=static_cast<B>(a);  // 编译报错, C类与A类没有任何关系
    return 1;
}

const_cast: const_cast操作不能在不同的种类间转换。相反,它仅仅把一个它作用的表达式转换成常量。它可以使一个本来不是const类型的数据转换成const类型的,或者把const属性去掉。
reinterpret_cast: 有着和C风格的强制转换同样的能力。它可以转化任何内置的数据类型为其他任何的数据类型,也可以转化任何指针类型为其他的类型。它甚至可以转化内置的数据类型为指针,无须考虑类型安全或者常量的情形。不到万不得已绝对不用。
dynamic_cast:
(1)其他三种都是编译时完成的,dynamic_cast是运行时处理的,运行时要进行类型检查。
(2)不能用于内置的基本数据类型的强制转换。
(3)dynamic_cast转换如果成功的话返回的是指向类的指针或引用,转换失败的话则会返回NULL。
(4)使用dynamic_cast进行转换的, 基类中一定要有虚函数,否则编译不通过。
        B中需要检测有虚函数的原因:类中存在虚函数,就说明它有想要让基类指针或引用指向派生类对象的情况,此时转换才有意义。
        这是由于运行时类型检查需要运行时类型信息,而这个信息存储在类的虚函数表(关于虚函数表的概念,详细可见<Inside c++ object model>)中,
        只有定义了虚函数的类才有虚函数表。
 (5)在类的转换时,在类层次间进行上行转换时,dynamic_cast和static_cast的效果是一样的。在进行下行转换时,dynamic_cast具有类型检查的功能,比               static_cast更安全。向上转换即为指向子类对象的向下转换,即将父类指针转化子类指针。向下转换的成功与否还与将要转换的类型有关,即要转换的指针指向的对象的实际类型与转换以后的对象类型一定要相同,否则转换失败。
参考例子:
复制代码 代码如下:

#include<iostream>
#include<cstring>
using namespace std;
class A
{
   public:
   virtual void f()
   {
       cout<<"hello"<<endl;
       };
};

class B:public A
{
    public:
    void f()
    {
        cout<<"hello2"<<endl;
        };

};

class C
{
  void pp()
  {
      return;
  }
};

int fun()
{
    return 1;
}
int main()
{
    A* a1=new B;//a1是A类型的指针指向一个B类型的对象
    A* a2=new A;//a2是A类型的指针指向一个A类型的对象
    B* b;
    C* c;
    b=dynamic_cast<B*>(a1);//结果为not null,向下转换成功,a1之前指向的就是B类型的对象,所以可以转换成B类型的指针。
    if(b==NULL)
    {
        cout<<"null"<<endl;
    }
    else
    {
        cout<<"not null"<<endl;
    }
    b=dynamic_cast<B*>(a2);//结果为null,向下转换失败
    if(b==NULL)
    {
        cout<<"null"<<endl;
    }
    else
    {
        cout<<"not null"<<endl;
    }
    c=dynamic_cast<C*>(a);//结果为null,向下转换失败
    if(c==NULL)
    {
        cout<<"null"<<endl;
    }
    else
    {
        cout<<"not null"<<endl;
    }
    delete(a);
    return 0;
}


http://www.jb51.net/article/36914.htm

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值