c++中四种cast转化

c++中四种cast转化

1.const_cast转化

const变量👉非const变量
•常量指针转化为非常量的指针,并且仍然指向原来的对象
•常量引用转化为非常量的引用,并且仍然指向原来的对象
(★const_cast只能改变运算对象的底层const,而对顶层const无能为力
★const_cast不能改变表达式类型,只能改变常量属性)

1.去掉const常量const属性
const int g = 20;
int h = const_cast<int>(&g);
2.去掉const引用const属性
const int g = 20; int &h = const_cast<int &>(g);
3.去掉const指针const属性
const char *g = “hello”; char *h = c
onst_cast<char *>(g);

使用:
1.一个函数的参数不是const对象,并且编程者事先已经知道在这个函数中不会对参 数进行修改,但需要传递的实参却是已经定义好的const对象。为了成功调用这个函数,就需要利用到const_cast在实参传递前对其进行处理,从而使函数能够成功接收这个实参

#include<iostream>
using namespace std;
void Function(int *val){
    cout<<*val<<endl;
}
int main(){
    const int value=21;
    Function(const_cast<int*>(&value));
    return 0;
}

2.如果我们定义了一个非const的变量,却使用了一个指向const对象的指针来指向它, 而在程序的某处希望改变这个变量时发现只有指针可用,此时就可const_cast进行处理

#include<iostream>
using namespace std;
int main(){
    int value=26;
    const int* const_ptr=&value;
    int* ptr=const_cast<int*>(const_ptr);
    *ptr=3;
    cout<<"value:"<<value<<endl;
    cout<<"*const_ptr:"<<*const_ptr<<endl;
    cout<<"ptr:" <<*ptr<<endl;
    return 0;
}

输出:
输出

2.static_cast转化

1.各种隐式转化
非const👉const,void*👉指针
2.能用于多态向上转化,向下转换可成功但不安全

用法
①用于类层次结构中基类(父类)和派生类(子类)之间指针或引用的转换。
进行上行转换(把派生类的指针或引用转换成基类表示)是安全的;
进行下行转换(把基类指针或引用转换成派生类表示)时,由于没有动态类型检查,所以是不安全的。
②用于基本数据类型之间的转换,如把int转换成char,把int转换成enum。这种转换的安全性也要开发人员来保证。
③把空指针转换成目标类型的空指针。
④把任何类型的表达式转换成void类型。
注意:static_cast不能转换掉expression的const、volatile、或者__unaligned属性。

基本数据类型

char a = 'a';
int b = static_cast<char>(a);//正确,将char型数据转换成int型数据

double *c = new double;
void *d = static_cast<void*>(c);//正确,将double指针转换成void指针

int e = 10;
const int f = static_cast<const int>(e);//正确,将int型数据转换成const int型数据

const int g = 20;
int *h = static_cast<int*>(&g);//编译错误,static_cast不能转换掉g的const属性

类上行和类下行转化

if(Derived *dp = static_cast<Derived *>(bp)){//下行转换是不安全的
  //使用dp指向的Derived对象  
}
else{
  //使用bp指向的Base对象  
}

if(Base*bp = static_cast<Derived *>(dp)){//上行转换是安全的
  //使用bp指向的Derived对象  
}
else{
  //使用dp指向的Base对象  
}

3.dynamic_cast转化

用于动态类型转化,只能用于含有虚函数的类,用于类层次之间的向上和向下转化。
⭐只能转指针或引用。

如果一条dynamic_cast语句的转换目标是指针类型并且失败了,则结果为0。如果转换目标是引用类型并且失败了,则dynamic_cast运算符将抛出一个std::bad_cast异常(该异常定义在typeinfo标准库头文件中)。

(1)指针类型:
举例,Base为包含至少一个虚函数的基类,Derived是Base的共有派生类,如果有一个指向Base的指针bp,我们可以在运行时将它转换成指向Derived的指针,代码如下:

if(Derived *dp = dynamic_cast<Derived *>(bp)){
  //使用dp指向的Derived对象  
}
else{
  //使用bp指向的Base对象  
}

(2)引用类型:
因为不存在所谓空引用,所以引用类型的dynamic_cast转换与指针类型不同,在引用转换失败时,会抛出std::bad_cast异常,该异常定义在头文件typeinfo中。

void f(const Base &b){
 try{
   const Derived &d = dynamic_cast<const Base &>(b);  
   //使用b引用的Derived对象
 }
 catch(std::bad_cast){
   //处理类型转换失败的情况
 }
}

4.reinterpret_cast转化

几乎什么都可以转
⭐new_type必须是一个指针、引用、算术类型、函数指针或者成员指针。

举一个错误使用reintepret_cast例子,将整数类型转换成函数指针后,vc++在执行过程中会报"…中的 0xxxxxxxxx 处有未经处理的异常: 0xC0000005: Access violation"错误:

#include <iostream>
using namespace std;
int output(int p){
    cout << p <<endl;
  return 0;
}

typedef int (*test_func)(int );//定义函数指针test_func
int main(){
    int p = 10;
    test_func fun1 = output;
    fun1(p);//正确
    test_func fun2 = reinterpret_cast<test_func>(&p);
    fun2(p);//...处有未经处理的异常: 0xC0000005: Access violation
    return 0;
}`

错误的使用reinterpret_cast很容易导致程序的不安全,只有将转换后的类型值转换回到其原始类型,这样才是正确使用reinterpret_cast方式。
MSDN中也提到了,实际中可将reinterpret_cast应用到哈希函数中,如下(64位系统中需将unsigned int修改为unsigned long):

// expre_reinterpret_cast_Operator.cpp
// compile with: /EHsc
#include <iostream>

// Returns a hash code based on an address
unsigned short Hash( void *p ) {
   unsigned int val = reinterpret_cast<unsigned int>( p );
   return ( unsigned short )( val ^ (val >> 16));
}

using namespace std;
int main() {
   int a[20];
   for ( int i = 0; i < 20; i++ )
      cout << Hash( a + i ) << endl;
}

5.为什么不使用强制转化?

c的强制转化表面上看起来功能强大,什么都可以转,但是转化不明确,不能进行错误检查,容易出错。
参考:“SpartacusIn21”博客

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
C++,子类和基类之间的转换可以通过类型转换实现。在进行子类和基类之间的转换时,需要注意以下几点: 1. 子类对象可以直接转换为基类对象,因为子类对象包含了基类对象的所有成员。 2. 基类对象不能直接转换为子类对象,因为基类对象不包含子类对象的成员。如果需要将基类对象转换为子类对象,则需要使用强制类型转换,但这种转换可能会导致编译错误或运行时错误。 3. 在进行子类和基类之间的指针转换时,可以使用dynamic_cast操作符进行安全转换。dynamic_cast操作符可以检查转换是否合法,如果转换不合法,则会返回空指针。 示例代码如下: ```c++ class Base { public: virtual void foo() { cout << "Base::foo() called" << endl; } }; class Derived : public Base { public: void foo() override { cout << "Derived::foo() called" << endl; } }; int main() { // 子类对象可以直接转换为基类对象 Derived d; Base &b = d; // 基类对象不能直接转换为子类对象 Base b2; // 编译错误:invalid static_cast from type 'Base' to type 'Derived&' // Derived &d2 = static_cast<Derived &>(b2); // 使用dynamic_cast进行安全转换 Base *pb = new Derived(); Derived *pd = dynamic_cast<Derived *>(pb); if (pd) { pd->foo(); // Derived::foo() called } else { cout << "dynamic_cast failed" << endl; } delete pb; return 0; } ``` 在上面的示例代码,定义了一个基类Base和一个子类Derived,其子类继承了基类。在main函数,首先将子类对象d转换为基类对象b,然后尝试将基类对象b2转换为子类对象d2,但这个转换是不合法的,会导致编译错误。接着定义了一个基类指针pb,将其指向子类对象,并使用dynamic_cast将其转换为子类指针pd,如果转换成功,则调用子类的foo方法,否则输出转换失败的信息。最后记得释放动态分配的内存。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hnu哈哈

请接受直女的么么哒????

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值