1.static_cast
用法:static_cast < type-id > ( expression )
该运算符把expression转换为type-id类型,但没有运行时类型检查来保证转换的安全性。它主要有如下几种用法:
①用于类层次结构中基类(父类)和派生类(子类)之间指针或引用的转换。
进行上行转换(把派生类的指针或引用转换成基类表示)是安全的;
进行下行转换(把基类指针或引用转换成派生类表示)时,由于没有动态类型检查(动态绑定),所以是不安全的。
②用于基本数据类型之间的转换,如把int转换成char,把int转换成float、non-const对象转换为const对象等是安全的。
③把空指针转换成目标类型的空指针。
④把任何类型的表达式转换成void类型。
1、C++中的static_cast执行非多态的转换,用于代替C中通常的转换操作。因此,被做为显式类型转换使用。比如:
int i = 65;
char j = static_cast<char>(i);
cout << j << endl;//结果为A
int i=2;
float j = static_cast<float>(i);
int型的2和float型的2,在内存中是由不同的二进制序列表示的。不过在执行static_cast<float>(i)
这一操作时,编译器会生成目标代码,将i的整型二进制表示转为i的浮点型二进制表示,这种叫做基于内容的转换,安全。
但是,static_cast也并非绝对安全,这是因为有void指针的存在。任何类型的指针都可以隐含地转换为void指针。如:
int i=2;
void *vp=&i;
这两句话本身没有安全性问题,因为void指针在语义上就是所指向对象的内容的数据类型不确定的指针,因此它可以指向任何类型的对象。但是,通过void指针不能对它所指向的对象进行任何操作,在执行操作之前,还需将void指针转换为具体类型的指针。C++不允许void指针到具体类型指针的转换隐含地发生,这种转换需要显式地进行,用static_cast即可。
int i = 2;
void *vp = &i;
int *p = static_cast<int*>(vp);//安全的
cout << *p << endl;
上面的例子如果将void类型转换为指针原来的类型(int*),那么是安全的,否则仍然是不安全的。
如:float *p = static_cast<float*>(vp);
不安全。
2.reinterpret_cast
C++中的reinterpret_cast主要是将数据从一种类型的转换为另一种类型。所谓“通常为操作数的位模式提供较低层的重新解释”也就是说将数据以二进制存在形式的重新解释。比如:
float i = 1.;
float *p = &i;
int j = reinterpret_cast<int>(p);//将指针p的值以二进制(位模式)的方式被解释为整型,并赋给i
cout << p << endl;
cout << j << endl;
此时结果,j与p的值是完全相同的。reinterpret_cast的作用是说将指针p的值以二进制(位模式)的方式被解释为整型,并赋给j,一个明显的现象是在转换前后没有数位损失。
再看另一个例子:
int i=2;
float*p=reinterpret_cast<float*>(&i);
cout<<p<<endl;
cout<<&i<<endl;//两句结果相同
这里把int类型的&i转化为float类型,这个转换是怎么进行的呢?无论是int类型的指针还是float类型的指针,存储的都是同一个地址,只是地址中的数据被解释被解释成不同类型而已。这种转换的结果就是,p作为浮点型指针,却指向了整型变量i,所以通过p访问整型变量i,肯定是有问题的,即*p的结果一定不为2.
3.const_cast
const_cast一般用于强制消除对象的常量性。它是唯一能做到这一点的C++风格的强制转型。这个转换能去除一个对象的const属性,它只能用于将常指针转换为普通指针,将常引用转换为普通引用。
接下来就到了本文的核心点!!!
class Text {
public:
const char& operator[](int pos)const
{
return text[pos];
}
char& operator[](int pos)
{
return text[pos];
}
Text(string s) :text(s) {}
private:
string text;
};
上述代码operator[]函数重载了两个版本,但是这不是最佳的选择,最佳的办法是使用none-const版本调用const版本,避免代码重复。这就要用到const_cast.
优化后的代码如下:
#include<iostream>
#include<string>
using namespace std;
class Text {
public:
const char& operator[](int pos)const
{
return text[pos];
}
char& operator[](int pos)//使用none-const版本调用const版本,避免代码重复
{
return const_cast<char&> //把const char& operator[]函数返回的常引用的const属性去除
(static_cast<const Text*>(this)->operator[](pos));//把this从原始类型Text*转换为const Text*,这样就可以调用常成员函数
//return const_cast<char&> //把const char& operator[]函数返回的常引用的const属性去除
// (static_cast<const Text&>(*this)[pos]);//把*this从原始类型Text&转换为const Text&,这样就可以调用常成员函数
}
Text(string s) :text(s) {}
private:
string text;
};
int main() {
Text s("abc");
const Text cs("abc");
cout << s[0] << endl;//使用none-const版本调用const版本,避免代码重复
cout << cs[0] << endl;//直接调用const版本
s[0] = 'x';
system("pause");
return 0;
}