类型转换
1. 隐式类型转换
2. 显式类型转换
类型做换形式
cast-name<type>(expression);
1> C++ 中兼容C中的强制类型转换
char c = 'A';
int i = (int)c;//C
int i = int (c);//C++
2> C++扩展了四种操作符形式的显示类型转换
a. 静态类型转化:static_cast
- 语法
目标变量 = static_cast<目标类型>(源类型变量);
- 使用场景
- 用于基本类型之间的转换,如把
int
转换为char
,把int
转换为enum
,但是这种转换的安全性需要程序员自己保证;如果在把int
转换为char
时,char
没有足够的bit
来存放int
的值(int>127 || int<-127
)那么static_cast
会做一个简单的截断,将int
的低八位复制到char
的八位中,直接抛弃高位 - 主要将泛型指针(
void*
) 的指针转换成其他类型的指针 - 用于类型层次结构中父类和子类之间指针和引用的转换(向上造型和向下造型),对于
static_cats
向上造型时安全的,向上造型可以看做是将权限缩小的操作,不会发生危险行为,而向下造型却是将权限放大的行为,所以是不安全的
- 注意:
static_cast
只在编译时进行类型检查,没有运行时的类型检查机制来保证转换的安全性,在程序中如果将指向子类对象的指针转换为指向父类类型的指针时,static_cast
不会报错也不会返回NULL指针,这种转换时存在潜在的风险的,运行时可能就会出现问题- 仅当类型之间可隐式转换时(除类层次向下造型),static_cast的转化才是合法的,否则将产生错误
b. 动态内存转换
dynamic_cast
- 语法
目标变量 = dynamic_cast<目标类型>(源类型变量);
- 使用场景
- 主要用于动态内存绑定
- 主要用于类层次结构中父类和子类之间指针和引用的转换,由于具有运行时类型检查的机制可以保证向下造型的安全性:(转换不合理的意思是将指向子类对象的指针或引用转换为指向父类对象的指针或引用,父类中并不会存在子类中的所有成员,如果用这种转换完的指针去访问父类中没有的成员时就会出现访问越界的问题导致程序崩溃)
- 返回值
- 对于指针类型的造型,在转换时成功会返回正确的类型的指针,如果转换失败,则返回空指针;
- 对于引用类型的造型,在转换时成功会返回正确的引用,如果失败会抛出
bad_cast
类型的异常;
- 注意:
dynamic_cast
具有运行时进行类型检查的机制,在运行时类型检查需要运行时类型信息,而这个信息存放在虚函数表中,只有定义了虚函数的类才有虚函数表,没有定义虚函数的类是没有虚函数表的,对于没有虚函数表的类使用dynamic_cast
会导致编译报错
c. 去常类型转换
const_cast
- 语法
目标变量 = const_cast<目标类型>(源类型变量);
使用场景
主要用于去掉指针或引用的常属性,改变运算对象底层的const
,底层const
表示指针或引用的指向的对象是一个常量,顶层const表示指针本身是个常量,对于将常量对象转化为非常量对象的行为我们称为"去掉const
性质",一旦我们去掉了某个对象的const
属性,编译器就不会再阻止我们对本来具有const
属性的对象进行写操作
注意:
volatile
关键字避免编译器对常量的优化
被volatile
修饰的变量是易变的,编译器每次使用此变量时,都从内存中重新读取,不要直接使用寄存器中的副本,防止编译器优化引发的错误结果
d. 重解释类型转换
reinterpret_cast
- 语法
目标变量 = reinterpret_cast<目标类型>(源类型变量);
- 使用场景
1>任意类型指针或引用之的显示转换
2>在指针类型和整数类型之间的显示转换
eg:向物理地址0x12345678
存放数据123
int *paddr = reinterpret_cast<int*>(0x12345678);
*paddr = 123;
- **Code
//去常类型转换:const_cast
#include <iostream>
using namespace std;
int main (void){
//volatile:标准C中的关键字
volatile const int ci =10; //ci是一个常量,指向ci的指针是const int* ci
int *pci = const_cast<int*>(&ci);//去常转换
*pci = 20;
cout<< "ci: "<<ci<<endl;//20
cout<<"*pci: "<<*pci<<endl;//20
cout<<"&ci: "<<(void*)&ci<<endl;
cout<<"pic: "<<(void*)&pci<<endl;
return 0;
}
//重解释类型转换:reinterpret_cast
#include <iostream>
using namespace std;
int main (void ){
//"\000"->'\0'
char buf[] = "0001\00012345678\000123456";
struct Http{
char type[5];
char id[9];
char passwd[7];
};
Http* ph = reinterpret_cast<Http*>(buf);
cout<<ph->type<<ph->id<<ph->passwd<<endl;
}
$ g++ reinterpret_cast.cpp
$ ./a.out
000112345678123456
总结
- 慎用宏,可以使用const enum,inline替换
- const
#define PAI 3.14
->const double PAI = 3.14;
- enum
#define SLEEP 0
#define RUN 1
#define STOP 2
->enum STATE{SLEEP,RUN,STOP};
- const
#define MAX(a,b) ((a)>(b)?(a):(b))
->inline int max(int a,int b){
return a > b ? a : b;
}
- 变量随用随声明同时初始化
- 尽量使用
new
delete
替换malloc
free
- 少用
void*
,指针计算,联合体,强制类型转换 - 尽量使用
string
表示字符串,少用c风格char*
、char[ ]