C++支持以下4种类型的转换运算符:
1. const_cast
2. static_cast
3. dynamic_cast
4. reinterpret_cast
1. const_cast
const_cast用于舍弃变量的常数。以下是有关const_cast的一些有趣的事实。
1) const_cast可用于更改const成员函数内的非const类成员。考虑以下代码片段。在const成员函数fun()中,编译器将“ this”视为“ const student * const this”,即“ this”是指向常量对象的常量指针,因此编译器不允许通过以下方式更改数据成员“这个”指针。 const_cast将“ this”指针的类型更改为“ student * const this”。
#include
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 (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会可用于常量数据传递到不接收常量的函数。例如,在下面的程序中,fun()接收普通指针,但是可以在const_cast的帮助下传递指向const的指针。
#include
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 (ptr);
cout << fun(ptr1);
return 0;
}
输出:
20
3)修改最初声明为const的值是未定义的行为。考虑以下程序。程序的输出未定义。变量“ val”是一个常量变量,并且调用“ fun(ptr1)”尝试使用const_cast修改“ val”。
#include
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 (ptr);
fun(ptr1);
cout << val;
return 0;
}
输出:
Undefined Behavior
修改最初未声明为const的值是可以的。例如,在上面的程序中,如果我们从val声明中删除const,则该程序将产生20作为输出。
#include
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 (ptr);
fun(ptr1);
cout << val;
return 0;
}
4) const_cast被认为比简单类型转换更安全。从某种意义上讲,如果强制类型与原始对象不相同,则强制强制转换不会发生,这是比较安全的。例如,以下程序编译失败,因为将“ int *”类型转换为“ char *”
#include
using namespace std;
int main(void)
{
int a1 = 40;
const int* b1 = &a1;
char* c1 = const_cast (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
#include
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 (b1);
cout << "typeid of c1 " << typeid(c1).name() << '\n';
return 0;
}
输出:
typeid of b1 PVKi
typeid of c1 Pi
锻炼
预测以下程序的输出。如果存在编译错误,请修复它们。
问题1
#include
using namespace std;
int main(void)
{
int a1 = 40;
const int* b1 = &a1;
char* c1 = (char *)(b1);
*c1 = 'A';
return 0;
}
问题2
#include
using namespace std;
class student
{
private:
const 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 (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;
}