C++的类型转换

16 篇文章 0 订阅

C语言中的类型转换

#include <stdio.h>
#include <Windows.h>

int main() {
	int i = 1;
	// 隐式类型转换
	double d = i;
	printf("%d\t%.2f\n", i, d);
	int* p = &i;
	// 强制类型转换
	int address = (int)p;
	printf("%p\t%d\n", p, address);
	system("pause");
	return 0;
}

在这里插入图片描述
C语言本身是一个强类型的语言, 但是对于相近类型还是会存在隐式转换的问题, 这使得C语言埋下了很多的坑, 比如说int与size_t的隐式类型转换导致循环不符合预期, 以及int(a) = int(a) + double(b)这种多次隐式类型转换导致损失效率等等.
不同类型能否可以进行强制类型转换, 这是由编译器决定的, 上述代码在vs下正常通过, 但是在其他编译器(比如说gcc)就不一定了.

C++强制类型转换

为了解决C语言中由于不明确的隐式类型转换而导致的各种问题, C++引入了可视化的强制类型转换. 但是这并没有从根本上解决问题, 仅仅是一种期望
static_cast:
静态转换, 用于两个相近类型的隐式转换

int main() {    
  int i = 1;    
  double d = static_cast<double>(i);    
  printf("%d\t%.2f\n", i, d);    
  return 0;    
}    

在这里插入图片描述
reinterpret_cast:
重新诠释转换, 用于两个不同类型的强制类型转换

int dosomething(int i) {                                                                                             
  cout << "dosomething" << endl;
  return 0;  
}  
int main() {      
  typedef void(*FUN)();      
  FUN f = reinterpret_cast<FUN>(dosomething);      
  f();      
}      

在这里插入图片描述
const_cast:
const转换, 用于删除const属性

int main() {    
  const int i = 1;    
  int* p = const_cast<int*>(&i);    
  *p = 100;    
  cout << i << endl;    
  cout << *p << endl;
}                           

在这里插入图片描述i的值并没有改变, 这是因为编译器优化的结果, 编译器将旧值i保存在寄存器中, 而i在内存中已经被修改了, 但是每次打印i的时候编译器都从寄存器中取而不是内存中.

volatile const int i = 1;

可以通过volatile关键字来防止编译器优化, 每次都去内存中取值
在这里插入图片描述
dynamic_cast:
动态转换, 用于将一个父类对象的指针转换为子类对象的指针或引用. 前提是这个父类具有多态性(即里面必须有虚函数表)

class A {    
  public:    
    virtual void show() {    
      cout << "A" << endl;    
    }    
};    
class B : public A {    
  public:    
    virtual void show() {    
      cout << "B" << endl;    
    }    
};    
void fun(A* pa) {
  B* pb1 = static_cast<B*>(pa);
  B* pb2 = dynamic_cast<B*>(pa);
  cout << pb1 << endl;
  cout << pb2 << endl;
  pb1->show();
}
void fun1() {
  A* pa = new A;
  B* pb1 = static_cast<B*>(pa);
  B* pb2 = dynamic_cast<B*>(pa);
  cout << pb1 << endl;
  cout << pb2 << endl;                                                                                          
  pb1->show();
}

在这里插入图片描述
将父类对象强转为子类对象, static_cast没有强转成功依然指向父类对象, 而dynamic_cast直接被置nullptr

void fun2() {    
  A* pa = new B;    
  B* pb1 = static_cast<B*>(pa);    
  B* pb2 = dynamic_cast<B*>(pa);    
  cout << pb1 << endl;    
  cout << pb2 << endl;    
  pb1->show();    
  pb2->show();    
}    

在这里插入图片描述
将指向的子类对象的父类指针强转为子类指针, static_cast与dynamic_cast都成功了.
建议:
避免使用强制类型转换

C++类型强转延伸

explicit:
阻止拷贝构造隐式转换为构造的过程

class A {                
  public:                
    explicit A(int a) : _a(a) {      
      cout << "A(int a)" << endl;      
    }                    
    A(const A& a) : _a(a._a) {      
      cout << "A(const A& a)" << endl;      
    }                    
    int getA() {         
      return _a;         
    }                    
  private:               
    int _a;              
};                       
int main() {             
  A a1(1);               
  cout << a1.getA() << endl;      
  //A a2 = 2; //不允许 A tmp(1) ---> A a2(tmp)                                                                                   
  //cout << a2.getA() << endl;    
  return 0;                                         
}                             

RTTI:
Run-time Type identification的简称,即:运行时类型识别。
C++通过以下方式来支持RTTI:

  1. typeid运算符
  2. dynamic_cast运算符
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值