C++从入门到放弃之:类型转换

类型转换

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<目标类型>(源类型变量);
  • 使用场景
  1. 用于基本类型之间的转换,如把int转换为char,把int转换为enum,但是这种转换的安全性需要程序员自己保证;如果在把int转换为char时,char没有足够的bit来存放int的值(int>127 || int<-127)那么static_cast会做一个简单的截断,将int的低八位复制到char的八位中,直接抛弃高位
  2. 主要将泛型指针(void*) 的指针转换成其他类型的指针
  3. 用于类型层次结构中父类和子类之间指针和引用的转换(向上造型和向下造型),对于static_cats向上造型时安全的,向上造型可以看做是将权限缩小的操作,不会发生危险行为,而向下造型却是将权限放大的行为,所以是不安全的
  • 注意:
  1. static_cast只在编译时进行类型检查,没有运行时的类型检查机制来保证转换的安全性,在程序中如果将指向子类对象的指针转换为指向父类类型的指针时,static_cast 不会报错也不会返回NULL指针,这种转换时存在潜在的风险的,运行时可能就会出现问题
  2. 仅当类型之间可隐式转换时(除类层次向下造型),static_cast的转化才是合法的,否则将产生错误

b. 动态内存转换
dynamic_cast

  • 语法
    目标变量 = dynamic_cast<目标类型>(源类型变量);
  • 使用场景
  1. 主要用于动态内存绑定
  2. 主要用于类层次结构中父类和子类之间指针和引用的转换,由于具有运行时类型检查的机制可以保证向下造型的安全性:(转换不合理的意思是将指向子类对象的指针或引用转换为指向父类对象的指针或引用,父类中并不会存在子类中的所有成员,如果用这种转换完的指针去访问父类中没有的成员时就会出现访问越界的问题导致程序崩溃)
  • 返回值
  1. 对于指针类型的造型,在转换时成功会返回正确的类型的指针,如果转换失败,则返回空指针;
  2. 对于引用类型的造型,在转换时成功会返回正确的引用,如果失败会抛出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替换
  1. const
#define PAI 3.14
	->const double PAI = 3.14;
  1. enum
#define SLEEP 0
#define RUN 1
#define STOP 2
	->enum STATE{SLEEP,RUN,STOP};
  1. 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[ ]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值