📜  C++中的const_cast |类型转换运算符

📅  最后修改于: 2021-05-25 20:35:20             🧑  作者: Mango

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;
}
要从最佳影片策划和实践问题去学习,检查了C++基础课程为基础,以先进的C++和C++ STL课程基础加上STL。要完成从学习语言到DS Algo等的更多准备工作,请参阅“完整面试准备课程”