一、const_cast用法
const_cast < new-type > ( expression );
用于转换指针或引用,可以去掉类型的const属性。
在c++参考文档网站上(const_cast conversion - cppreference.com)有这么一个例子:
#include <iostream>
struct type
{
int i;
type(): i(3) {}
void f(int v) const
{
// this->i = v; //直接赋值,会编译报错;因为const成员函数,意味着该函数内不能改变当前类成员的值
const_cast<type*>(this)->i = v; // 只要type对象不是 const 就可以对类成员进行改值了
}
};
int main()
{
int i = 3; // i is not declared const
const int& rci = i;
const_cast<int&>(rci) = 4; // OK: modifies i
std::cout << "i = " << i << '\n';
type t;//如果声明为const type t, 那么下一个语句t.f(4),就是一个未定义的行为,所以不要加const了
t.f(4);
std::cout << "type::i = " << t.i << '\n';
const int j = 3;
[[maybe_unused]]/*抑制针对未使用实体的警告。*/
int* pj = const_cast<int*>(&j);通过强制转换,将const常量的地址赋值给普通指针
// *pj = 4; //通过普通指针修改const常量的值,这是未定义的行为,不要这么写;结果后面例子1会进一步演示这个现象
[[maybe_unused]]
void (type::* pmf)(int) const = &type::f; // pointer to member function
// const_cast<void(type::*)(int)>(pmf); // 编译错误:const_cast 对函数指针不生效
}
--------------------------------------------------------------------
输出:
i = 4
type::i = 4
例1:
#include <iostream>
using namespace std;
int main(){
const int a = 10;
cout << a << endl;
int *p = const_cast<int*>(&a);
*p = 1;
cout << *p << endl;
cout << a << endl;
return 0;
}
------------------------
输出:
10
1
10
但是当你调试这段程序的时候,你会发现a是改变了的,而且不同的编译器可能有不同的表现,所以说这样用是未定义的行为。

备注: 函数后加const的意义:
类的成员函数中,常常有一些成员函数不改变类的数据成员,这些函数是"只读"函数,而有一些函数要修改类数据成员的值。把不改变数据成员的函数后面都加上const关键字进行标识,可提高程序的可读性。定义成const的成员函数,内部编码修改数据成员的值,编译器会报错。
二、reinterpret_cast
作用:重新解释类型,既不检查指向的内容,也不检查指针类型本身;但要求转换前后的类型所占用内存大小一致,否则引发编译时错误。由于太过于灵活,所以要慎用。
#include <cstdint>
#include <cassert>
#include <iostream>
int f() { return 42; }
int main()
{
int i = 7;
// 指向整数并返回的指针
std::uintptr_t v1 = reinterpret_cast<std::uintptr_t>(&i);
std::cout << "The value of &i is " << std::showbase << std::hex << v1 << '\n';
int *p1 = reinterpret_cast<int *>(v1);
assert(p1 == &i);
char* p2 = reinterpret_cast<char*>(&i);
std::cout << (p2[0] == '\x7' ? "This system is little-endian\n"
: "This system is big-endian\n");
// 指向另一个函数并返回的指针
void(*fp1)() = reinterpret_cast<void(*)()>(f);
//经过强制转换,然后调用
int(*fp2)() = reinterpret_cast<int(*)()>(fp1);
std::cout << std::dec << "通过fp2 调用函数 " << fp2() << '\n';
}
三、static_cast
用于基本类型转换,有继承关系类对象和类指针之间的转换,由程序员来确保转换是安全的,它不会产生动态转换的类型安全检查的开销。
#include "iostream"
using namespace std;
int main(){
int vlu1 = 666;
cout << vlu1 << endl;
double vlu2 = static_cast<double >(vlu1);
cout << vlu2 << endl;
double vlu3 = 66.6;
cout << vlu3 << endl;
int vlu4 = static_cast<int>(vlu3);
cout << vlu4 << endl;//丢失精度
}
四、dynamic_cast
只能用于含有虚函数的类,必须用在多态体系中,用于类层次间的向上和向下转化;向下转化(父类转成子类)时,如果是非法的对于指针返回NULL。
#include "iostream"
using namespace std;
class Base{
public:
Base():_i(0){;};
~Base(){;};
virtual void T(){cout << "TTTT:" << _i <<endl;}
private:
int _i;
};
class Derived: public Base{
public:
Derived():_j(1){;};
~Derived(){;};
virtual void T(){cout << "Derived:" << _j << endl;};
private:
int _j;
};
int main(){
Base cb;
Derived cd;
Base *pcb;
Derived* pcd;
//子类转父类
pcb = static_cast<Base*>(&cd);
if(pcb == nullptr){
cout << "danger action 1" << endl;
}
pcb = dynamic_cast<Base*>(&cd);
if(pcb == nullptr){
cout << "danger action 2" << endl;
}
//父类转子类
pcd = static_cast<Derived*>(&cb);
if(pcd == nullptr){
cout << "danger action 3" << endl;
}
pcd = dynamic_cast<Derived*>(&cb);
if(pcd == nullptr){
cout << "danger action 4" << endl;
}
}
输出:
danger action 4
本文详细介绍了C++中const_cast和reinterpret_cast的使用方法。const_cast用于移除变量的const属性,但不安全,可能会导致未定义行为。reinterpret_cast则非常灵活,用于类型重新解释,但要求转换前后类型内存大小一致。同时,文章还简述了static_cast和dynamic_cast的作用。
3390





