C++ --- 强制转换运算符
Posted Overboom
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++ --- 强制转换运算符相关的知识,希望对你有一定的参考价值。
1. 隐式转换
C/C++中的类型转换分为两种:隐式类型转换和显示类型转换。
隐式类型转换服从向下兼容的原则:
char x = 5;
int y = x; //将char转换为int,即是隐式转换
2. 显示转换(强制类型转换)
C语言中典型的强制类型转换
int *p = (char *) x;
C++对C兼容,上面的转换方式是可行的,但是有时候会有问题,所以C++新增了四个强制类型转换关键字
const_cast<type> (expr): const_cast 运算符用于修改类型的 const / volatile 属性。除了 const 或 volatile 属性之外,目标类型必须与源类型相同。这种类型的转换主要是用来操作所传对象的 const 属性,可以加上 const 属性,也可以去掉 const 属性。
dynamic_cast<type> (expr): dynamic_cast 在运行时执行转换,验证转换的有效性。如果转换未执行,则转换失败,表达式 expr 被判定为 null。dynamic_cast 执行动态转换时,type 必须是类的指针、类的引用或者 void*,如果 type 是类指针类型,那么 expr 也必须是一个指针,如果 type 是一个引用,那么 expr 也必须是一个引用。
reinterpret_cast<type> (expr): reinterpret_cast 运算符把某种指针改为其他类型的指针。它可以把一个指针转换为一个整数,也可以把一个整数转换为一个指针。
static_cast<type> (expr): static_cast 运算符执行非动态转换,没有运行时类检查来保证转换的安全性。例如,它可以用来把一个基类指针转换为派生类指针。
2.1 const_cast应用举例
用于删除 const、volatile 和 __unaligned 特性(如将 const int 类型转换为 int 类型 )
1> const_cast可用于更改const成员函数内的非const类成员。看下面的示例代码
#include <iostream>
using namespace std;
class student
{
private:
int roll;
public:
// 构造函数
student(int r):roll(r) {}
// 在const_cast的帮助下改变roll的const函数
void fun() const
{
( const_cast <student*> (this) )->roll = 5;
}
int getRoll() { return roll; }
};
int main(int argc, char const *argv[])
{
student s(3);
cout << "Old roll number: " << s.getRoll() << endl;
s.fun();
cout << "New roll number: " << s.getRoll() << endl;
return 0;
}
编译输出结果;
2> const_cast可用于将const数据传递给不接收const的函数。例如:
#include <iostream>
using namespace std;
int fun(int* ptr)
{
return (*ptr + 10);
}
int main(int argc, char const *argv[])
{
const int val = 10;
const int *ptr = &val;
int *ptr1 = const_cast <int *>(ptr);
cout << fun(ptr1)<<endl;
return 0;
}
编译输出:
3> const_cast也可以用来抛弃volatile属性。例如:
#include <iostream>
#include <typeinfo> // typeid
using namespace std;
int main(int argc, char const *argv[])
{
int a1 = 40;
const volatile int* b1 = &a1;
cout << "typeid of b1 " << typeid(b1).name() << '\\n';
int* c1 = const_cast <int *> (b1);
cout << "typeid of c1 " << typeid(c1).name() << '\\n';
return 0;
}
编译输出:
2.2 reinterpret_cast
它用于转换任何类型的另一个指针的一个指针,而不管该类是否相互关联。它不检查指针类型和指针所指向的数据是否相同。
用法如下:
reinterpret_cast <数据类型*>(指针变量);
看一个示例:
#include <iostream>
using namespace std;
int main(int argc, char const *argv[])
{
int* p = new int(65);
char* ch = reinterpret_cast<char*>(p);
cout << *p << endl;
cout << *ch << endl;
cout << p << endl;
cout << ch << endl;
return 0;
}
编译输出:
2.3 dynamic_cast
dynamic_cast的转换格式:
dynamic_cast <type-id> (expression)
将expression转换为type-id类型,type-id必须是类的指针、类的引用或者是void *;如果type-id是指针类型,那么expression也必须是一个指针;如果type-id是一个引用,那么expression也必须是一个引用。
最简单的上行转换,比如Derived 继承自Basic,Derived 转换为Basic,进行上行转换时,是安全的,如下:
#include <iostream>
using namespace std;
class Basic{
public:
virtual int test(){return 0;} // 必须为多态以使用运行时检查的 dynamic_cast
};
class Derived : public Basic{
public:
int test(){return 1;}
};
int main(int argc, char const *argv[]){
Basic cBasic;
Derived cDerived;
Basic * pB1 = new Basic;
Basic * pB2 = new Derived;
//动态强制转换失败,因此pD1为空。
Derived * pD1 = dynamic_cast<Derived * > (pB1);
//动态强制转换成功,因此rD2引用派生对象。
Derived & rD2 = dynamic_cast<Derived &> (*pB2);
return 0;
}
编译结果:
2.4 static_cast
static_cast通常用于转换数据类型(float->int)
1> 代码段一示例
#include <iostream>
using namespace std;
int main(int argc, char const *argv[])
{
float f = 4.5;
int a = f; //C-style
int b = static_cast<int>(f);
cout << b << endl;
return 0;
}
编译输出:
2> 对上面的代码进行修改
#include <iostream>
using namespace std;
int main(int argc, char const *argv[])
{
int a = 10;
char c = 'a';
int* q = (int*) &c;
int *p = static_cast<int *>(&c);//编译错误,static_cast 不能将字符转换成指针
return 0;
}
编译输出:
这意味着,即使您认为可以将特定对象类型转换为另一个对象,但这是非法的,static_cast也不允许这样做。
static_cast 用于基本数据类型之间的转换,如把int转换成char,把int转换成float。在c++ primer 中说道:c++ 的任何的隐式转换都是使用 static_cast 来实现。
3> 让我们以继承为例,来看看这个例子:
#include <iostream>
using namespace std;
class Base {
};
class Derived : public Base {
};
int main(int argc, char const *argv[])
{
Derived d1;
Base* b1 = (Base*)(&d1); // 允许
Base* b2 = static_cast<Base*>(&d1);
return 0;
}
编译输出:
编译,上面的代码将不会出现任何错误。
1、我们取&d1,显式的存入Base中,存储在b1中。
2、我们取&d1,用static_cast将其转换成Base,存储在b2中。
我们知道static_cast执行严格的类型检查,让我们稍微修改一下代码看看,把继承改为private。
4>
#include <iostream>
using namespace std;
class Base {
};
class Derived : private Base {
};
int main(int argc, char const *argv[])
{
Derived d1;
Base* b1 = (Base*)(&d1); // 允许
Base* b2 = static_cast<Base*>(&d1);
return 0;
}
编译输出:
即使继承为受保护的,上面的代码也不会编译。因此,要使用static_cast,请将其继承为public。
5> 使用static_cast将“向空指针”和“从空指针”进行强制转换。例子:
#include <iostream>
using namespace std;
int main(int argc, char const *argv[])
{
int i = 10;
void* v = static_cast<void*>(&i);
int* ip = static_cast<int*>(v);
return 0;
}
编译输出:
参看链接:
https://www.runoob.com/cplusplus/cpp-casting-operators.html
https://blog.csdn.net/chen1415886044/article/details/104565863
https://www.cnblogs.com/Allen-rg/p/6999360.html
以上是关于C++ --- 强制转换运算符的主要内容,如果未能解决你的问题,请参考以下文章