C/C++类型转换

1.隐式类型转换

1.1 隐式类型转换的规则

K & R A.6.5 
Arithmetic Conversions(数值型间的转换)
First, if either operand is long double, the other is converted to long double.
Otherwise, if either operand is double, the other is converted to double.
Otherwise, if either operand is float, the other is converted to float.
Otherwise, the integral promotions are performed on both operands; then, if either operand is unsigned long int, the other is converted to unsigned long int.
Otherwise, if one operand is long int and the other is unsigned int, the effect depends on whether a long int can represent all values of an unsigned int; if so, the unsigned int operand is converted to long int; if not, both are converted to unsigned long int.
Otherwise, if one operand is long int, the other is converted to long int.
Otherwise, if either operand is unsigned int, the other is converted to unsigned int.
Otherwise, both operands have type int.

[包含浮点型的运算]
如果任意一个操作数是long double, 那么另一个要转换为 long double
如果任意一个操作数是double,         那么另一个要转换为 double
如果任意一个操作数是float,             那么另一个要转换为 float
[2个非浮点型的运算]
如果任意一个操作数是unsigned long int, 那么另一个要转换为unsigned long int
如果一个操作数是long int, 另一个是unsigned int, 如果long int可以表示结果,那么unsigned int要转换为long int,否则两个都转换为unsigned long int
如果任意一个操作数是long int, 那么另一个要转换为long int
如果任意一个操作数是unsigned int, 那么另一个要转换为unsigned int
除此之外,两个操作数都应是int

1.2  发生隐式类型转换的条件

① 有多种数据类型的算术表达式

② 将一种类型的数据赋值给另一种类型的变量.(将等号右边的结果 转换 成 左边变量的类型)

③ 函数调用中, 实参与形参类型不同,返回值类型 与 函数声明不同.(实参转成形参类型, 返回值转成 函数声明类型) 

2.显示类型转换(强制类型转换)

2.1 显示转换的写法

写法主要有 2 中, 其中一种是C++独有

int a = 4;

//1. (type) exp  ;C and C++
float b = (float)a;

//2 type (exp)   ;C++ only
float c = float (a); 

2.2 C++强制类型转换运算符

 在C++中,有 4 个强制类型转换运算符,分别是:static_cast、dynamic_cast、const_cast 和 reinterpret_cast。 

2.2.1、static_cast

静态强制转换,用于实现任何标准类型间的转换。 

2.2.2、dynamic_cast

动态强制转换,用于基类 和 派生类 对象之间的指针转换,以实现多态。

dynamic_cast是在程序运行的时刻实现的,其他强制转换实在编译时就完成了. 

#include <iostream>

class Base
{
public:
    int varB;
    virtual void func(void){std::cout<<"Base::func"<<std::endl;}
};
class Derived:public Base
{
public:
    int varD;
    virtual void func(void){std::cout<<"Derived::func"<<std::endl;}
};


void func1(Base *pb)
{
    Derived *pd1 = static_cast<Derived *>(pb);
    std::cout<<"pd1 = "<<pd1<<std::endl;
    pd1->func();
    std::cout<<"varD = "<<pd1->varD<<std::endl; // 访问非法内存

    Derived *pd2 = dynamic_cast<Derived *>(pb);
    std::cout<<"pd2 = "<<pd2<<std::endl;        // pd2 是空指针
    pd2->func();                                // 程序崩溃
}

void func2(Derived *pd)
{
    Derived *pd1 = static_cast<Derived *>(pd);
    std::cout<<"pd1 = "<<pd1<<std::endl;
    pd1->func();
    std::cout<<"varD = "<<pd1->varD<<std::endl;

    Derived *pd2 = dynamic_cast<Derived *>(pd);
    std::cout<<"pd2 = "<<pd2<<std::endl;
    pd2->func();
}

int main(void)
{
    Base bs;
    Base *pb = &bs;
    
    Derived dd;
    Derived *pd = &dd;
    
    func1(pb);
    func2(pd);

    return 0;
}

 使用dynamic_cast时Base类中必须有虚函数,否则会编译出错;static_cast则没有这个限制。

Base中需要检测有虚函数的原因:由于运行时类型检查需要运行时类型信息,而这个信息存储在类的虚函数表中。
类中存在虚函数,就说明它有想要让基类指针或引用指向派生类对象的情况,此时转换才有意义。 

2.2.3、const_cast

常量强制转换,用于强制转换 const或volatile 的数据,转换前后数据的类型必须相同,

主要用来在运算时暂时删除数据的const限制。

问题:http://bbs.csdn.net/topics/390741544

 

2.2.4、reinterpret_cast

重解释强制转换,是按照强制转换所指定的类型 对 被转换数据对应的内存空间 进行重新定义

例如将int型和指针型之间的相互转换。

#include <iostream>

int main(void)
{
    int i = 0;
    char *pch = "Hello";

    i = reinterpret_cast<int>(pch);
    
    std::cout<<reinterpret_cast<char *>(i)<<std::endl;
    
    return 0;
}

/*---- 输出结果---------
Hello
-----------------------*/

  

----------------------------------------------------------------------------------------------------------------

参考资料:

<<C++面向对象程序设计(第二版)>>

 http://baike.baidu.com/link?url=t2_gReiazbNzDC506qpVVY9ynuOIeEwsQgBZ0A2uTrogCujubSr-Nb93A_xRpAa4R43G0HjRnNAu1M_ohqgzMa

posted @ 2014-03-25 14:42  LubinLew  阅读(535)  评论(0编辑  收藏  举报