类型转换的含义是 通过改变一个变量的类型为别的类型从而改变该变量的表示方式。为了类型转换一个简单对象为另一个对象你会使用传统的类型转换操作符
c风格的强制类型转换,不管什么是什么类型,统统都是Type b = (Type)a;
c++风格的类型转换提供了4种类型转换操作符来应对不同场合的的应用
static_cast<> 静态类型转换 用于基础数据类型,还有继承关系的指针或引用
dynamic_cast<> 只能转换有继承关系的指针或引用,只能由子类转父类(基类)
const_cast<> 增加或去除 变量的const性
reinterpret_cast<> 强制类型转换,可用于没有任何关联之间的转换
static_cast<>
//1 static_cast<>测试
class Building{};
class Animal{};
class Cat:public Animal{};
void test03(){
//1 转换基本数据类型(整型 浮点型 字符型)
int a=65;
char c=static_cast<char>(a);
cout<<a<<"---"<<c<<endl; //ok 可以转换
//2 转换基本指针类型(已存在的指针类型)
int *x=NULL;
//char *y=static_cast<char*>(x); //error 不能转换
//3 无关系的类指针转换
Building *build=NULL;
//Animal *animal1=static_cast<Animal*>(build); //error 不能转换
//4 无继承关系的类引用转换
Building b;
Building &lb=b;
//Animal &lani=static_cast<Animal&>(lb); //error 不能转换
//5 具有继承关系的父<=>子类的指针转换
Animal *animal2=NULL;
Cat *cat=static_cast<Cat*>(animal2); //ok 指针父转子 即小转大 但类型不安全 容易造成非法访问内存
Cat *cat2=NULL;
Animal *animal3=static_cast<Animal*>(cat2); //ok 指针子转父 即大转小 类型安全
//6 具有继承关系的父<=>子类的引用转换
Animal an1;
Animal &lan1=an1;
Cat &c1=static_cast<Cat&>(lan1); //ok 引用父转子 即小转大 但类型不安全 容易造成非法访问内存
Cat c2;
Cat &lc2=c2;
Animal &an2=static_cast<Animal&>(lc2); //ok 引用子转父 即大转小 类型安全
//总结:1 static_cast<> 可以用于基本数据类型转换 有继承关系的父子类指针和引用(1,5,6)
// 2 不能用于基本指针类型的转换 不能用于无继承关系的类指针、引用转换(2,3,4)
}
dynamic_cast<>
//2 dynamic_cast
void test04(){
//1 基本数据类型的转换
int a = 10;
//char c = dynamic_cast<char>(a); //error
//2 基本指针类型的转换
int *x=NULL;
//char *c=dynamic_cast<char*>(x); //erroe
//3 无关系的类指针转换
Animal* ani = NULL;
//Building* building = dynamic_cast<Building*>(ani); //error
//4 无关系的类引用转换
Animal ani2;
Animal &lani=ani2;
//Cat &c2=dynamic_cast<Cat&>(lani); //error
//5 具有继承关系的父<=>子类的指针转换
Animal* ani3= NULL;
//Cat* cat1 = dynamic_cast<Cat*>(ani3); //error dynamic会做类型安全检查 小转大 不安全
Cat* cat2 = NULL;
Animal* ani4 = dynamic_cast<Animal*>(cat2); //ok 大转小 类型安全
//6 具有继承关系的父<=>子类的引用转换
Animal ani5;
Animal &lani5=ani5;
//Cat &cat3=dynamic_cast<Cat&>(lani5); //error dynamic会做类型安全检查 小转大 不安全
Cat cat4;
Cat &lcat4=cat4;
Animal &lani6=dynamic_cast<Animal&>(lcat4); //ok 大转小 类型安全
//结论: dynamic只能转换具有继承关系的指针或者引用 并且只能由子类转成父类
}
const_cast<>
class A{
public:
A(int data){
m_data=data;
}
int m_data;
};
//3.1 const_cast<>对有内存的对象转换时
void test01(){
const A a(1);
//A &a1=a; error const对象的引用必须用const引用去接
//a.m_data=2; error 不可以修改const对象的数据
//1 去掉a的const 用普通对象去接 普通对象能修改他的数据 原对象不能修改
A a1=const_cast<A&>(a); //尖括号中只能是指针或引用
//a.m_data=100; //error 原对象不能修改
a1.m_data=2; //普通对象修改他的数据
cout<<a.m_data<<' '<<a1.m_data<<endl; //输出1 2 a与a1不是同一个对象
//2 去掉a的const后 用引用a2去接 引用能修改他的数据 原对象不能修改 但是会随着引用的改变而改变
A& a2=const_cast<A&>(a);
//a.m_data=100; //error 原对象不能修改
a2.m_data=3; // 引用能修改他的数据
cout<<a.m_data<<' ' <<a2.m_data<<endl; //输出3 3 原对象会随着引用的改变而改变
//总结:引用去掉const的对象时 引用的改变会引起原对象的改变 但原对象仍是const 不能通过其修改
//指针时
//A *a3=const_cast<A*>(&a); //ok
//A *a3=&a; //error const A的地址不能赋给A的地址 与引用一样
//const A *a3=&a; //ok 但是a3不能修改a的值 因为没有去除a的const
A *a3=const_cast<A*>(&a);
a3->m_data=100;
cout<<a.m_data<<' '<<a3->m_data<<endl; //100 100
//指针的值改变 原对象的值也会改变 因为指向同一内存
//总结:指针指向去掉const的对象时 指针的改变会引起原对象的改变
}
//3.2 const_cast<>对存储在符号表的对象转换时
void test02(){
const int x=3; //常量引用不会开辟内存 所以此语句x被放在符号表 常引用会即const int &x=3;
//1 引用
int &x1=const_cast<int&>(x); //开辟内存,实际上是编译器帮我们temp=3;int &x1=temp;x仍被放在符号表
x1=300; //这就是下面引用和指针改变,x不会改变的原因
cout<<x<<" "<<x1<<endl; //3 300 基本类型的引用改变 原变量不会发生改变
//2 指针
int *x2=const_cast<int*>(&x);
*x2=400;
cout<<x<<" "<<*x2<<endl; //3 400 基本类型的指针改变 原变量不会发生改变
//3 也可以增加const
int p1=10;
//const int p2=const_cast<const int>(p1); //error 因为const_cast<>尖括号里必须是指针或引用
int* p3 = NULL;
const int* p4 = const_cast<const int*>(p3); //ok
//总结:特殊的 const int x=3并不会开辟内存,当给x起引用或者指针时 引用和指针的改变并不会影响到本身x
}
//这个例子有三个结论:
//总结1:引用去掉const的对象时 引用的改变会引起原对象的改变 但原对象仍是const 不能通过其修改
//总结2:指针指向去掉const的对象时 指针的改变会引起原对象的改变
//总结3:特殊的 const int x=3并不会开辟内存,当给x起引用或者指针时 引用和指针的改变并不会影响到本身x
reinterpret_cast<>
//4 reinterpret_cast<>
typedef void(*FUNC1)(int, int);
typedef int(*FUNC2)(int, char*);
void test05(){
//1. 转换基础数据类型
int a = 65;
char c = reinterpret_cast<char>(a); //打印出字符c为A ASCII码
//int a = 10;
//char c = reinterpret_cast<char>(a); //error a是整型常量,转为char型容易造成非法访问内存
//2. 无关的指针类型都可以进行转换
Building* building = NULL;
Animal* ani = reinterpret_cast<Animal*>(building);
//3. 函数指针转换
FUNC1 func1;
FUNC2 func2 = reinterpret_cast<FUNC2>(func1);
//总结:reinterpret_cast<> 强制类型转换,无关的指针类型,函数指针,对象指针都可以转换
// 可以看做C语言的强制转换 几乎所有都能转 但建议少用 容易出错
}