1.static_cast
基本等价于隐式转换的一种类型转换运算符,以前是编译器自动隐式转换,static_cast可使用于需要明确隐式转换的地方。c++中用static_cast用来表示明确的转换。 可以用于低风险的转换: 整型和浮点型
字符与整形
转换运算符
空指针转换为任何目标类型的指针
不可以用与风险较高的转换: 不同类型的指针之间互相转换 整型和指针之间的互相转换 不同类型的引用之间的转换
2.const_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;
};
现在可以有针对的修改其中的成员
3.dynamic_cast
定义两个简单的类:
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,若指向的为父类空间,则也不会报错,更加灵活。
4.reinterpret_cast重新诠释
执行各种高风险转换,如整型转指针,各种类型的指针转换,父类子类指针的转换
int i=1;
int*a=reinterpret_cast(int*)i;
等价于c中的强制转换:
int i=1;
int*a=(int*)i;
|