C++支持以下4种类型的转换运算符:
- const_cast
- static_cast
- dynamic_cast
- reinterpret_cast
1. const_cast
const_cast用于舍弃变量的常数。以下是有关const_cast的一些有趣的事实。
1)const_cast可用于更改const成员函数内的非const类成员。考虑以下代码片段。在const成员函数fun()中,编译器将“ this”视为“const student * const this”,即“ this”是指向常量对象的常量指针,因此编译器不允许通过以下方式更改数据成员 “this”指针。const_cast将“ this”指针的类型更改为“ student * const this”。
#include <iostream>
using namespace std;
class student
{
private:
int roll;
public:
// constructor
student(int r):roll(r) {}
// A const function that changes roll with the help of const_cast
void fun() const
{
( const_cast <student*> (this) )->roll = 5;
}
int getRoll() { return roll; }
};
int main(void)
{
student s(3);
cout << "Old roll number: " << s.getRoll() << endl;
s.fun();
cout << "New roll number: " << s.getRoll() << endl;
return 0;
}
输出:
Old roll number: 3
New roll number: 5
2)const_cast可用于将const数据传递给不接收const的函数。例如,在下面的程序中,fun()接收普通指针,但是可以在const_cast的帮助下传递指向const的指针。
#include <iostream>
using namespace std;
int fun(int* ptr)
{
return (*ptr + 10);
}
int main(void)
{
const int val = 10;
const int *ptr = &val;
int *ptr1 = const_cast <int *>(ptr);
cout << fun(ptr1);
return 0;
}
输出:
20
3)修改最初声明为const的值是未定义的行为。考虑下面的程序。程序的输出未定义。变量“ val”是一个常量变量,调用“ fun(ptr1)”尝试使用const_cast修改“ val”。
#include <iostream>
using namespace std;
int fun(int* ptr)
{
*ptr = *ptr + 10;
return (*ptr);
}
int main(void)
{
const int val = 10;
const int *ptr = &val;
int *ptr1 = const_cast <int *>(ptr);
fun(ptr1);
cout << val;
return 0;
}
输出:
Undefined Behavior
修改最初未声明为const的值是可以的。例如,在上述程序中,如果我们从val声明中删除const,则该程序将产生20作为输出。
#include <iostream>
using namespace std;
int fun(int* ptr)
{
*ptr = *ptr + 10;
return (*ptr);
}
int main(void)
{
int val = 10;
const int *ptr = &val;
int *ptr1 = const_cast <int *>(ptr);
fun(ptr1);
cout << val;
return 0;
}
4)const_cast比简单类型转换更安全。从某种意义上讲,如果投射类型与原始对象不同,则不会发生投射,这是比较安全的。例如,以下程序编译失败,因为将“ int *”类型转换为“ char *” 。
#include <iostream>
using namespace std;
int main(void)
{
int a1 = 40;
const int* b1 = &a1;
char* c1 = const_cast <char *> (b1); // compiler error
*c1 = 'A';
return 0;
}
输出:
prog.cpp: In function ‘int main()’:
prog.cpp:8: error: invalid const_cast from type 'const int*' to type 'char*'
5)const_cast也可以用来抛弃volatile属性。例如,在下面的程序中,b1的typeid是PVKi(指向易失性和恒定整数的指针),而c1的typeid是Pi(指向整数的指针)。
#include <iostream>
#include <typeinfo>
using namespace std;
int main(void)
{
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;
}
输出:
typeid of b1 PVKi
typeid of c1 Pi
2. Static Cast
这是可以使用的最简单的类型转换。它是一个编译时间转换,它可以进行类型之间的隐式转换(例如int到float或指向void *的指针),还可以调用显式转换函数(或隐式函数)。
示例:
#include <iostream>
using namespace std;
int main()
{
float f = 3.5;
int a = f; // this is how you do in C
int b = static_cast<int>(f);
cout << b;
}
输出:
3
3. reinterpret_cast
reinterpret_cast是C ++中使用的一种强制转换运算符。
- 它用于转换任何类型的另一个指针的一个指针,无论该类是否相互关联。
- 它不检查指针类型和指针所指向的数据是否相同。
语法:
data_type *var_name =
reinterpret_cast <data_type *>(pointer_variable);
示例:
// CPP program to demonstrate working of
// reinterpret_cast
#include <iostream>
using namespace std;
int main()
{
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;
}
输出:
65
A
0x1609c20
A
使用reinterpret_cast的目的
1)reinterpret_cast是一种非常特殊且危险的类型转换操作符。建议使用正确的数据类型使用它,即(指针数据类型应与原始数据类型相同)。
2)它可以将任何指针类型转换为任何其他数据类型。
3)当我们要使用位时使用它。
4)如果我们使用这种类型的cast,那么它将成为一种不可移植的产品。因此,除非需要,建议不要使用这个概念。
5)它仅用于将任何指针转换为原始类型。
6)布尔值将转换为整数值,即0表示false,1表示true。
// CPP code to illustrate using structure
#include <bits/stdc++.h>
using namespace std;
// creating structure mystruct
struct mystruct {
int x;
int y;
char c;
bool b;
};
int main()
{
mystruct s;
// Assigning values
s.x = 5;
s.y = 10;
s.c = 'a';
s.b = true;
// data type must be same during casting
// as that of original
// converting the pointer of 's' to,
// pointer of int type in 'p'.
int* p = reinterpret_cast<int*>(&s);
cout << sizeof(s) << endl;
// printing the value currently pointed by *p
cout << *p << endl;
// incrementing the pointer by 1
p++;
// printing the next integer value
cout << *p << endl;
p++;
// we are casting back char * pointed
// by p using char *ch.
char* ch = reinterpret_cast<char*>(p);
// printing the character value
// pointed by (*ch)
cout << *ch << endl;
ch++;
/* since, (*ch) now points to boolean value,
so it is required to access the value using
same type conversion.so, we have used
data type of *n to be bool. */
bool* n = reinterpret_cast<bool*>(ch);
cout << *n << endl;
// we can also use this line of code to
// print the value pointed by (*ch).
cout << *(reinterpret_cast<bool*>(ch));
return 0;
}
输出:
12
5
10
a
1
1
程序2
// CPP code to illustrate the pointer reinterpret
#include <iostream>
using namespace std;
class A {
public:
void fun_a()
{
cout << " In class A\n";
}
};
class B {
public:
void fun_b()
{
cout << " In class B\n";
}
};
int main()
{
// creating object of class B
B* x = new B();
// converting the pointer to object
// referenced of class B to class A
A* new_a = reinterpret_cast<A*>(x);
// accessing the function of class A
new_a->fun_a();
return 0;
}
输出:
In class A