传统C语言的 内部类型转换 :
C语言传统的转化很简单。
比如:
double d=5.0;
int a=(int)d;
这个感觉和java差不多。
C++有四个内部类型转换操作符: const_cast ,reinterpret_cast,static_cast,dynamic_cast。
const_cast
用法:const_cast<type_id> (expression)
该运算符用来修改类型的const或volatile属性。除了const 或volatile修饰之外, type_id和expression的类型是一样的。
一、常量指针被转化成非常量指针,并且仍然指向原来的对象;
二、常量引用被转换成非常量引用,并且仍然指向原来的对象;
三、常量对象被转换成非常量对象。
Voiatile和const类试。举如下一例:
class B
{
public:
int m_iNum;
B()
{
;
}
};
void foo()
{
const B b1;
//b1.m_iNum = 100; //comile error
B& b2 = const_cast<B&>(b1);
b2. m_iNum = 200; //fine?
}
int main()
{
foo();
return 0;
}
上面的代码编译时会报错,因为b1是一个常量对象,不能对它进行改变;
使用const_cast把它转换成一个非常量对象引用,就可以对它的数据成员任意改变。
C语言传统的转化很简单。
比如:
double d=5.0;
int a=(int)d;
这个感觉和java差不多。
用法:const_cast<type_id> (expression)
该运算符用来修改类型的const或volatile属性。除了const 或volatile修饰之外, type_id和expression的类型是一样的。
一、常量指针被转化成非常量指针,并且仍然指向原来的对象;
二、常量引用被转换成非常量引用,并且仍然指向原来的对象;
三、常量对象被转换成非常量对象。
Voiatile和const类试。举如下一例:
class B
{
public:
int m_iNum;
B()
{
;
}
};
void foo()
{
const B b1;
//b1.m_iNum = 100; //comile error
B& b2 = const_cast<B&>(b1);
b2. m_iNum = 200; //fine?
}
int main()
{
foo();
return 0;
}
上面的代码编译时会报错,因为b1是一个常量对象,不能对它进行改变;
使用const_cast把它转换成一个非常量对象引用,就可以对它的数据成员任意改变。
const_cast用于
类型转换掉表达式的
const
或
volatileness
属性。通过使用
const_cast,你向人们和编译器强调你通过类型转换想做的只是改变一些东西的
constness或者
volatileness属性。这个含义被编译器所约束。
如果你试图使用const_cast来完成修改constness 或者volatileness属性之外的事情,你的类型转换将被拒绝 。
reinterpret_cast
reinterpret_cast是C++里的强制类型转换符。 它的本质是重新解释引用或者指针所对应的比特模型(类型),引用或者指针所指向的内存区域的数据不会变化。
例1:
reinterpret_cast是C++里的强制类型转换符。 它的本质是重新解释引用或者指针所对应的比特模型(类型),引用或者指针所指向的内存区域的数据不会变化。
例1:
int *n= new int ;
double *d=reinterpret_cast<double*> (n);
例2:
double *d=reinterpret_cast<double*> (n);
例2:
int n=9;
double &d= reinterpret_cast<double&> (n);
在进行计算以后, d 包含无用值. 这是因为引用或者指针所指向的内存区域的数据不会变化。 reinterpret_cast 仅仅重新解释引用或者指针所对应的比特模型(类型),而 static_cast 却进行了二进制转换
例如:
int n=9; double d=static_cast < double > (n);
double &d= reinterpret_cast<double&> (n);
在进行计算以后, d 包含无用值. 这是因为引用或者指针所指向的内存区域的数据不会变化。 reinterpret_cast 仅仅重新解释引用或者指针所对应的比特模型(类型),而 static_cast 却进行了二进制转换
例如:
int n=9; double d=static_cast < double > (n);
上面的例子中, 我们将一个变量从 int 转换到 double。 这些类型的二进制表达式是不同的。
要将整数 9 转换到 双精度 整数 9, static_cast 需要正确地为双精度整数 d 补足比特位。其结果为 9.0。
而reinterpret_cast 的行为却不同:
例3:
int n=9;
double d=reinterpret_cast<double & > (n);
这次, 结果有所不同. 在进行计算以后, d 包含无用值. 这是因为reinterpret_cast仅仅重新解释引用或者指针所对应的比特模型(类型)
因此, 你需要谨慎使用 reinterpret_cast.
注意:在例3中n和d的确对应不同的内存单元。
它似乎和reinterpret_cast仅仅重新解释引用或者指针所对应的比特模型(类型)相矛盾。
其实不矛盾。例3的本质如下:
int n=9;
reinterpret_cast<double & > temp=reinterpret_cast<double & > (n);
double d=temp; //注意这里本质是拷贝。当然n和d的确对应不同的内存单元
static_cast
用法: static_cast < type-id > ( expression )
该运算符把expression转换为type-id类型,但没有运行时类型检查来保证转换的安全性。它主要有如下几种用法:
①用于类层次结构中基类(父类)和派生类(子类)之间指针或引用的转换。
进行上行转换(把派生类的指针或引用转换成基类表示)是安全的;
进行下行转换(把基类指针或引用转换成派生类表示)时,由于没有动态类型检查,所以是不安全的。
②用于基本数据类型之间的转换,如把int转换成char,把int转换成enum。这种转换的安全性也要开发人员来保证。
③把空指针转换成目标类型的空指针。
④把任何类型的表达式转换成void类型。
注意: static_cast不能转换掉expression的const、volitale、或者__unaligned属性。
C++中 static_cast和reinterpret_cast的区别
C++primer第五章里写了编译器隐式执行任何类型转换都可由 static_cast显示完成; reinterpret_cast通常为操作数的位模式提供较低层的重新解释
1、 C++中的static_cast执行非多态的转换,用于代替C中通常的转换操作。因此,被做为隐式类型转换使用。比如:
int i;
float f = 166.7f;
i = static_cast<int>(f);
此时结果,i的值为166。
2、 C++中的reinterpret_cast主要是将数据从一种类型的转换为另一种类型。所谓“通常为操作数的位模式提供较低层的重新解释”
也就是说将数据以二进制存在形式的重新解释。比如:
int i;
char *p = "This is a example.";
i = reinterpret_cast<int>(p);
此时结果,i与p的值是完全相同的。reinterpret_cast的作用是说将指针p的值以二进制(位模式)的方式被解释为整型,
并赋给i,//i 也是指针,整型指针;一个明显的现象是在转换前后没有数位损失。
dynamic_cast
用法: dynamic_cast < type-id > ( expression )
该运算符把expression转换成type-id类型的对象。Type-id必须是类的指针、类的引用或者void *;
如果type-id是类指针类型,那么expression也必须是一个指针,如果type-id是一个引用,那么expression也必须是一个引用。
dynamic_cast主要用于类层次间的上行转换和下行转换,还可以用于类之间的交叉转换。
在类层次间进行上行转换时,dynamic_cast和static_cast的效果是一样的; 在进行下行转换时,dynamic_cast具有类型检查的功能,比static_cast更安全。
class B {
public:
int m_iNum;
virtual void foo();
};
class D : public B{
public:
char *m_szName[100];
};
void func(B *pb){
D *pd1 = static_cast<D *>(pb);
D *pd2 = dynamic_cast<D *>(pb);
}
在上面的代码段中,如果pb指向一个D类型的对象,pd1和pd2是一样的,并且对这两个指针执行D类型的任何操作都是安全的;
但是,如果pb指向的是一个B类型的对象,那么pd1将是一个指向该对象的指针,对它进行D类型的操作将是不安全的(如访问m_szName),
而pd2将是一个空指针。
注意:B要有虚函数,否则会编译出错;static_cast则没有这个限制。
作为四个内部类型转换操作符之一的
dynamic_cast
和传统的C风格的强制类型转换有着巨大的差别。除了
dynamic_cast
以外的转换,
其行为的都是在编译期就得以确定的,转换是否成功,并不依赖被转换的对象。而 dynamic_cast 则不然 。
首先,
dynamic_cast
依赖于RTTI信息
,其次,在转换时,
dynamic_cast
会检查转换的source对象是否真的可以转换成target类型,这种检查不是语法上的,而是真实情况的检查。先看
RTTI
相关部分,通常,许多编译器都是通过vtable找到对象的RTTI信息的,
这也就意味着,如果基类没有虚方法,也就无法判断一个基类指针变量所指对象的真实类型,
这时候, dynamic_cast 只能用来做安全的转换,例如从派生类指针转换成基类指针.而这种转换其实并不需要dynamic_cast参与.也就是说, dynamic_cas t是根据RTTI记载的信息来判断类型转换是否合法的.
另外,
dynamic_cast还支持交叉转换(cross cast)
。如下代码所示。
class A{
public:
int m_iNum;
virtual void f(){}
};
class B:public A{
};
class D:public A{
};
void foo(){
B *pb = new B;
pb->m_iNum = 100;
D *pd1 = static_cast<D *>(pb); //compile error
D *pd2 = dynamic_cast<D *>(pb); //pd2 is NULL
delete pb;
}
在函数foo中,使用
static_cast进行转换是不被允许的,将在编译时出错;而使用
dynamic_cast的转换则是允许的,结果是空指针
。
下面再看一个例子:
struct B1 {
virtual ~B1(){}
};
struct B2 {
virtual ~B2(){}
};
struct D1 : B1, B2{};
int main()
{
D1 d;
B1* pb1 = &d;
B2* pb2 = dynamic_cast<B2*>(pb1); //L1
B2* pb22 = static_cast<B2*>(pb1); //L2
return 0;
}
上述定义中可以看到,B1和B2是不相关的类,从L1可以看到, dynamic_cast允许这种转换:只要B1存在多态方法.
L2将编译失败,
static_cast并不允许两个完全不相干的类互相转换.
困惑:http://zhidao.baidu.com/question/56811956.html
要将整数 9 转换到 双精度 整数 9, static_cast 需要正确地为双精度整数 d 补足比特位。其结果为 9.0。
而reinterpret_cast 的行为却不同:
例3:
int n=9;
double d=reinterpret_cast<double & > (n);
这次, 结果有所不同. 在进行计算以后, d 包含无用值. 这是因为reinterpret_cast仅仅重新解释引用或者指针所对应的比特模型(类型)
因此, 你需要谨慎使用 reinterpret_cast.
注意:在例3中n和d的确对应不同的内存单元。
它似乎和reinterpret_cast仅仅重新解释引用或者指针所对应的比特模型(类型)相矛盾。
其实不矛盾。例3的本质如下:
int n=9;
reinterpret_cast<double & > temp=reinterpret_cast<double & > (n);
double d=temp; //注意这里本质是拷贝。当然n和d的确对应不同的内存单元
用法: static_cast < type-id > ( expression )
该运算符把expression转换为type-id类型,但没有运行时类型检查来保证转换的安全性。它主要有如下几种用法:
①用于类层次结构中基类(父类)和派生类(子类)之间指针或引用的转换。
进行上行转换(把派生类的指针或引用转换成基类表示)是安全的;
进行下行转换(把基类指针或引用转换成派生类表示)时,由于没有动态类型检查,所以是不安全的。
②用于基本数据类型之间的转换,如把int转换成char,把int转换成enum。这种转换的安全性也要开发人员来保证。
③把空指针转换成目标类型的空指针。
④把任何类型的表达式转换成void类型。
注意: static_cast不能转换掉expression的const、volitale、或者__unaligned属性。
C++中 static_cast和reinterpret_cast的区别
C++primer第五章里写了编译器隐式执行任何类型转换都可由 static_cast显示完成; reinterpret_cast通常为操作数的位模式提供较低层的重新解释
1、 C++中的static_cast执行非多态的转换,用于代替C中通常的转换操作。因此,被做为隐式类型转换使用。比如:
int i;
float f = 166.7f;
i = static_cast<int>(f);
此时结果,i的值为166。
2、 C++中的reinterpret_cast主要是将数据从一种类型的转换为另一种类型。所谓“通常为操作数的位模式提供较低层的重新解释”
也就是说将数据以二进制存在形式的重新解释。比如:
int i;
char *p = "This is a example.";
i = reinterpret_cast<int>(p);
此时结果,i与p的值是完全相同的。reinterpret_cast的作用是说将指针p的值以二进制(位模式)的方式被解释为整型,
并赋给i,//i 也是指针,整型指针;一个明显的现象是在转换前后没有数位损失。
用法: dynamic_cast < type-id > ( expression )
该运算符把expression转换成type-id类型的对象。Type-id必须是类的指针、类的引用或者void *;
如果type-id是类指针类型,那么expression也必须是一个指针,如果type-id是一个引用,那么expression也必须是一个引用。
dynamic_cast主要用于类层次间的上行转换和下行转换,还可以用于类之间的交叉转换。
在类层次间进行上行转换时,dynamic_cast和static_cast的效果是一样的; 在进行下行转换时,dynamic_cast具有类型检查的功能,比static_cast更安全。
class B {
public:
int m_iNum;
virtual void foo();
};
class D : public B{
public:
char *m_szName[100];
};
void func(B *pb){
D *pd1 = static_cast<D *>(pb);
D *pd2 = dynamic_cast<D *>(pb);
}
在上面的代码段中,如果pb指向一个D类型的对象,pd1和pd2是一样的,并且对这两个指针执行D类型的任何操作都是安全的;
但是,如果pb指向的是一个B类型的对象,那么pd1将是一个指向该对象的指针,对它进行D类型的操作将是不安全的(如访问m_szName),
而pd2将是一个空指针。
注意:B要有虚函数,否则会编译出错;static_cast则没有这个限制。
其行为的都是在编译期就得以确定的,转换是否成功,并不依赖被转换的对象。而 dynamic_cast 则不然
这也就意味着,如果基类没有虚方法,也就无法判断一个基类指针变量所指对象的真实类型,
这时候, dynamic_cast 只能用来做安全的转换,例如从派生类指针转换成基类指针.而这种转换其实并不需要dynamic_cast参与.也就是说, dynamic_cas t是根据RTTI记载的信息来判断类型转换是否合法的.
另外,
class A{
public:
int m_iNum;
virtual void f(){}
};
class B:public A{
};
class D:public A{
};
void foo(){
B *pb = new B;
pb->m_iNum = 100;
D *pd1 = static_cast<D *>(pb); //compile error
D *pd2 = dynamic_cast<D *>(pb); //pd2 is NULL
delete pb;
}
下面再看一个例子:
struct B1 {
virtual ~B1(){}
};
struct B2 {
virtual ~B2(){}
};
struct D1 : B1, B2{};
int main()
{
D1 d;
B1* pb1 = &d;
B2* pb2 = dynamic_cast<B2*>(pb1); //L1
B2* pb22 = static_cast<B2*>(pb1); //L2
return 0;
}
上述定义中可以看到,B1和B2是不相关的类,从L1可以看到, dynamic_cast允许这种转换:只要B1存在多态方法.
困惑:http://zhidao.baidu.com/question/56811956.html