您的位置:首页 > 汽车 > 时评 > 邢台市住建局_可以打开任何网站的软件_大数据免费查询平台_百度网盘客服人工电话95188

邢台市住建局_可以打开任何网站的软件_大数据免费查询平台_百度网盘客服人工电话95188

2025/4/29 11:37:06 来源:https://blog.csdn.net/2301_79927432/article/details/147591048  浏览:    关键词:邢台市住建局_可以打开任何网站的软件_大数据免费查询平台_百度网盘客服人工电话95188
邢台市住建局_可以打开任何网站的软件_大数据免费查询平台_百度网盘客服人工电话95188

目录

一 C语言中的类型转换

二 . C++强制类型转换 

1. static_cast

2. reinterpret_cast

3. const_cast

4. dynamic_cast

三 explicit 关键字 


 

一 C语言中的类型转换

在C语言中,如果赋值运算符左右两侧类型不同,或者形参与实参类型不匹配,或者返回值类型与接收返回值 类型不一致时,就需要发生类型转化,C语言中总共有两种形式的类型转换:隐式类型转换和显式类型转换

  • 隐式类型转化:编译器在编译阶段自动对相近类型进行转换
int main()
{int i = 1;double d = 6.66;i = d;//在这里编译器进行了隐式类型转换(前提相近类型)//将double转成int类型cout << i << endl;return 0;
}

运行结果会有一定的精度损失

  • . 显式类型转化:需要用户自己处理 (处理不相近类型)
    int* p = nullptr;p = (int*)i;//不相近类型,需要我们手动进行强制转换类型cout << p << endl;

缺陷: 转换的可视性比较差,所有的转换形式都是以一种相同形式书写,难以跟踪错误的转换。 


二 . C++强制类型转换 

 c++兼容c语言留下来的隐式类型转换和显示类型转换,但是c++觉得c语言做的不规范,且可视性比较差,为了加强类型转换的可视性,引入了四种命名的类型转换操作符。

static_cast、      reinterpret_cast、    const_cast、     dynamic_cast

1. static_cast

//对应c语言的隐式类型转换(相近类型)d=static_cast<double>(i);

2. reinterpret_cast

//对应c语言的强制类型转换(不相近类型)p = reinterpret_cast<int*>(i);

static_cast<>() 类似个类的使用,所以在使用上我们传模板<double>已经传参数(i)   

3. const_cast

    const int ci = 10;int* pi = const_cast<int*>(&ci);//去掉const属性//对应c语言的强制类型转换  int* pi = (int*)&ci;

接下来我们看一个测试题

int main()
{const int ci = 10;int* pi = const_cast<int*>(&ci);//去掉const属性//对应c语言的强制类型转换  int* pi = (int*)&ci;*pi = 20;cout << *pi << endl;cout << ci << endl;//return 0;}

测试结果

按理说所得结果ci应该为ci=20的,但是这里为啥还是10? 关于这种问题,在linux相关文章中也介绍过了,在main()中, 由于const int ci=10, 编译器会认为 const ci不会改变的,所以cpu会把ci存储在cpu里的寄存器中,不再每次向内存中读取ci的值了,所以后面尽管*pi=20即将ci对应的内存值改成20,但因为cpu并没有去读取,所以输出结果依然ci=10. 

 🍎在之前的文章中也介绍过,要想让寄存器到内存中读取const int ci 的值,我们需要在其前面加一个关键词  volatile (即内存可见)

    volatile const int ci = 10;int* pi = const_cast<int*>(&ci);//去掉const属性//对应c语言的强制类型转换  int* pi = (int*)&ci;*pi = 20;cout << *pi << endl;cout << ci << endl;//

测试结果:这样就符号我们的预期了

4. dynamic_cast

dynamic_cast     用于将一个父类对象的指针/引用转换为子类对象的指针或引用(动态转换)

  •     c++中子类对象可以赋值给父亲的对象指针引用,这个过程会发生切片,天然支持
A a;B b;A* pa = &a;pa = &b;
  • 如果父类的指针或引用传给子类的指针,这个过程有可能成功
class A
{
public://虚函数virtual void f(){}int _a;
};
class B :public A
{
public://虚函数virtual void f(){}int _b;
};//A a;
//B b;
//A* pa = &a;
//f_cast(pa);
//pa = &b;
//f_cast(pa);
void f_cast(A* pa)
{//如何区分pa是指向父类还是子类B* pb = (B*)pa;pb->_a = 1;pb->_b = 2;cout << pb->_a << endl;cout << pb->_b << endl;}
int main()
{A a;B b;A* pa = &a;//pa = &b;f_cast(pa);return 0;
}

这个测试例子主要是用于:pa是父类对象A的指针,当我们传过去给f_cast(pa),函数内部会将pa转成B* 类型的,那我们传入了父类指针能调用 pb->_a = 1; pb->_b = 2;吗?答案是不行的

若我们  pa = &b;   f_cast(pa);即将子类对象指针传入会怎么样呢?

所以c语言中的 void f_cast(A* pa)   B* pb = (B*)pa;pb->_a = 1;  pb->_b = 2;  并不能帮我们区分pa是指向父类还是子类。而c++中的dynamic_cast<B*>(pa) 就能很好解决这个问题。

void f_cast(A* pa)
{//如何区分pa是指向父类还是子类//如果pa指向子类对象,则转换成功//如果pa指向父类对象转换失败返回nullptrB* pb = dynamic_cast<B*>(pa);if (pb != nullptr){cout << "指向子类对象" << endl;pb->_a = 1;pb->_b = 2;}else{cout << "转换失败" << endl;}
}

注意:dynamic_cast只能用于含有虚函数的类 (父类需要有虚函数)这是为什么呢?

因为dynamic_cast通过 ---->去虚表上方的存储标识信息来知道到底是那个类。

还有一个混淆点,虚继承对应有虚基表,虚函数的多态对应虚表。


三 explicit 关键字 

我们先看一个例子:

 class A{public ://构造函数A (int a){cout<<"A(int a)" <<endl;}//拷贝构造A(const A& a){cout<<"A(const A& a)" <<endl;}private :int _a ;};int main (){A a1 (1);// 隐式转换-> A tmp(1); A a2(tmp);//即先构造tmp(1) 然后再拷贝A a2(tmp)A a2 = 1;}

这也是我们之前在写模拟STL的时候为什么构造函数和拷贝构造创建好之后也可以不用重载=

因为A  a2=1;编译器会进行 隐式转换。

为了阻止这种行为我们可以用explicit 关键字。explicit关键字阻止经过转换构造函数进行的隐式转换的发生

  explicit A (int a){cout<<"A(int a)" <<endl;}

当不进行=赋值重载再运行代码的时候会报错。

 

 

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com