基本等价于隐式转换的一种类型转换运算符,以前是编译器自动隐式转换,static_cast可使用于需要明确隐式转换的地方。c++中用static_cast用来表示明确的转换。
可以用于低风险的转换:
整型和浮点型
字符与整形
转换运算符
空指针转换为任何目标类型的指针
不可以用与风险较高的转换:
不同类型的指针之间互相转换
整型和指针之间的互相转换
不同类型的引用之间的转换
const_cast的对象类型必须为指针引用或指向对象的指针
用法1:
int main()
{
const int a = 1;
int*b = const_cast<int*>(&a);
*b = 5;
std::cout << a;
}
断点查看运行到*b = 5;时a的值被设为5了,但最后cout的a的值仍然为1
why?
对于const数据我们更要这样保证:绝对不对const数据进行重新赋值。
如果我们不想修改const变量的值,那我们又为什么要去const呢?
原因是,我们可能调用了一个参数不是const的函数,而我们要传进去的实际参数却是const的,但是我们知道这个函数是不会对参数做修改的。于是我们就需要使用const_cast去除const限定,以便函数能够接受这个实际参数。
用法2:
class father
{
virtual void func()const
{
void* p = this;
}
int aa;
};
func()为常成员函数,即通过该函数不可修改类的成员变量
常成员函数的this指针为const xxx型,即指向的地方的数据不能变,于是使用const_cast:
class father
{public:
virtual void func()const
{
const_cast<father*>(this)->aa = 1;
}
int aa;
};
现在可以有针对的修改其中的成员
还有类似的用法:
#include
int main() {
// 原始数组
int ary[4] = { 1,2,3,4 };
// 打印数据
for (int i = 0; i < 4; i++)
std::cout << ary[i] << "\t";
std::cout << std::endl;
// 常量化数组指针
const int*c_ptr = ary;
//c_ptr[1] = 233; //error
// 通过const_cast 去常量
int *ptr = const_cast<int*>(c_ptr);
// 修改数据
for (int i = 0; i < 4; i++)
ptr[i] += 1; //pass
// 打印修改后的数据
for (int i = 0; i < 4; i++)
std::cout << ary[i] << "\t";
std::cout << std::endl;
return 0;
}
/* out print
1 2 3 4
2 3 4 5
*/
小结:
1、常量指针被转化成非常量的指针,并且仍然指向原来的对象;
2、常量引用被转换成非常量的引用,并且仍然指向原来的对象;
3、const_cast一般用于修改指针。如const char *p形式。
4、const_cast不能修改const数据本身的值,但是可以去掉const指针的const属性来改变其指向的值
定义两个简单的类:
class father
{
};
class son:public father
{
public:
int num;
};
将父类指针转换为子类指针:
int main()
{
father f1;
son s1;
father* pfather=&f1;
son* pson = &s1;
son* pson = pfather;
}
此时pson虽然为子类指针,但他实际指向的是父类对象的空间,编译器认为可能通过该指针访问到此空间中不存在的部分,因此编译不能通过。
因此使用dynamic_cast(动态转换)通过RTTI(运行时类型识别)来做转换,而RTTI通过虚函数来实现,因此在父类里添加一个虚函数:
class father
{
virtual void func() {};
};
此时再做转换,即使访问了不存在的对象在编译阶段将不会出错:
int main()
{
father f1;
son s1;
father* pfather=&f1;
son* pson = &s1;
pson = dynamic_cast<son*>(pfather);
pson->num = 1;
}
而是在运行阶段时报错,并将pson置为空:
于是可以这样修改主函数:
int main()
{
father f1;
son s1;
father* pfather=&f1;
son* pson = &s1;
pson = dynamic_cast<son*>(pfather);
if(pson!=nullptr)
pson->num = 1;
}
若pson在程序运行时指向的为子类空间,则可以修改num,若指向的为父类空间,则也不会报错,更加灵活。
执行各种高风险转换,如整型转指针,各种类型的指针转换,父类子类指针的转换
int i=1;
int*a=reinterpret_cast(int*)i;
等价于c中的强制转换:
int i=1;
int*a=(int*)i;
static_cast虽然也不是一种绝对安全的转换,但是它在转换时,还是会进行必要的检测(诸如指针越界计算,类型检查)。reinterpret_cast完全是肆无忌惮,直接从二进制开始重新映射解释,是极度不安全的,再次提醒,不到万不得已,不要使用。