一、C语言类型
隐式----自动转换
char a = 'a';
int b = a;
显示---强制转换 ---- () ----不管目标类型是什么,都可以将源类型转换过去,属于比较暴力行为
int a = 100;
char b = (char)a;
二、C++,除了继承C语言中的类型转换之外(不推荐),还提供四种类型转换方式
static_cast 静态类型转换,它大多数情况下,跟C语言类型转换差不多
reinterpret_cast 重新解释强制类型转换,一般指针使用
dynamic_cast 动态的强制类型转换,一般使用在继承中,如子类和父类之间的多态类型转换
const_cast 去const属性的强制类型转换,字面上就是去掉某个变量 的const属性
4种类型强制的语法格式:
目标类型 目标 = static_cast<目标类型>(源);
比如:
int a = 123;
char b = static_cast<char>(a);
2.1 static_cast (静态类型转换)
1.用于基本数据类型以及对象之间的转换(char,int等)
2.用于继承关系类对象指针之间的转换
3.用于继承类指针之间转换
4.不能用于基本数据类型指针之间的转换(char* ,int*等)
关于继承中的对象指针的步长分析:
class Test
{
//对于类而言,无参构造 有参构造 拷贝构造,除此之外,类型转换构造
public:
//类型转换构造函数 ---- 特征:参数类型---int 参数个数:一个 函数名:类名
// explicit Test(int i)
// {
// cout << "i = " << i << endl;
// }
explicit Test(int age,string name="zhang3",char sex = 'W')
{
}
void test()
{
}
private:
int age;
string name;
char sex;
};
void test1()
{
//基本数据类型
int i = 2;
char c = 'c';
c = static_cast<char>(i);
// char* pi = (char*)&i; ok
// char* pi = static_cast<char*>( &i); //error
}
void test2()
{
//基本数据类型与对象之间转换
// main.cpp:43:10: error: no viable conversion from 'int' to 'Test'
// Test t1 = 3; //会隐式调用类型转换构造函数 ,如果参数的个数不是一个,那么它会报转换错误
Test t2(3); //跟上面这个等式,他们都会调用一个为整型参数的构造函数,但是,意义不一样
// Test t1 = 3; 使用整型值转换成一个类类型 ----防止这种现象
//Test t2(3); 实例化对象t2时,传入一个整型参数
// t1.test();
// 为了防止将基本的整型转换成类对象,在实现构造函数时,一般说明要可以进行显示的类型关系
// 在定义构造函数前,使用一个关键字explicit ,使构造函数只能进行显示转换,不能进行隐式转换
}
class Base
{
public:
Base(int m)
{
this->m = m;
cout<< " Base(int m)" << endl;
}
int m;
};
class Derived :public Base
{
public:
int val;
Derived(int m,int val):Base(m)
{
this->val = val;
cout << "Derived(int m,int val) " << endl;
}
};
int main()
{
// test1();
// test2();
Base* p = new Base(2);
Derived* d = static_cast<Derived*>(p); //指向是没有问题,但是,不安全
cout << d->val << " " << d->m << endl;
d->val = 100;
cout << d->val << " " << d->m << endl;
cout << p->m << endl;
d->m = 200;
cout << d->val << " " << d->m << endl;
return 0;
}
2.2 dynamic_cast (动态类型转换)
1.用于有继承关系的类指针(引用)转换
2.具有类型检查的功能,编译时会查检语法是否正确,程序运行时,才知道要转换的类型,
当转换为指针时
转换成功:得到目标类型指针
转换失败:得到一个空指针
当转换引用时:
转换成功:得到目标类型引用
转换失败:得到一个异常操作信息
3.不能用于基本数据指针之间的转换(char*,int*等)
4.(源)类中必须有虚函数的支持
class Base
{
public:
Base()
{
cout << " Base()" << endl;
}
virtual void funcA()
{
cout << "Base::funcA() "<<endl;
}
void funccAA()
{
cout << "Base::funccA() "<<endl;
}
virtual ~Base()
{
}
};
class Base1
{
public:
Base1()
{
cout << " Base()" << endl;
}
virtual void funcB()
{
cout << "Base1::funcB() "<<endl;
}
void funccBB()
{
cout << "Base1::funccB() "<<endl;
}
virtual ~Base1()
{
}
};
class Child:public Base,public Base1
{
public:
virtual void funcA()
{
cout << "Child::funcA() "<<endl;
}
};
int main()
{
Base* p = new Base; // 初始化父类指针
Child* pc = static_cast<Child*>(p); //强制之后,可以得到 地址,但是,操作不安全
cout << "pc = " << pc << endl;
//在C++中,通常父类与子类之间的转换
//main.cpp:26:17: error: 'Base' is not polymorphic
//C++中,想要构成多态,那么有虚函数的支持 通常将父类的析构函数设置为虚析构函数
Child* pc1 = dynamic_cast<Child*>(p);
cout << "pc1" << pc1 << endl; //转换失败,打印0地址
//在实际的开发过程中,使用以下形式来写代码
if(nullptr == pc1)
{
cout << "转换失败" << endl;
}
delete p;
Child * pc2 = new Child;
p = pc2;
/多重继承下的类指针转换//
Child c;
Base* pd = &c;
pd->funcA();
//通过强制转换执行
// Base1* pb = static_cast<Base1*>(pd); //不能将 Base* ----> Base1*
// Base1* pb1 = (Base1*)pd;
Base1* pb = dynamic_cast<Base1*>(pd);
pb->funcB(); //Base1::funcB()
// 编译器会去检测pd所在的地址,发现有多个虚函数表,然后根据Base1*来修正pb
pb->funccBB();
return 0;
}
2.3 reinterpret_cast --解读类型转换
用于所有的指针的强制转换(解读:对要转换的数据进行重新解读) 用于进行各种不同类型的指针之间,不同类型引用之间转换,转换的安全性得不到保证
class Derived
{
};
int main()
{
int i = 3;
char c = 'c';
int* pi = &i;
char* pc = reinterpret_cast<char*>(&i);
Derived d;
// int* p = (int*)&d; //C语言暴力强制
//它体现 C++语言设计思想,用可以做任何操作,但要为自己的行为负责
int* p = reinterpret_cast<int*>(&d);
//不能使用普通类型之间的转换
int j = 2;
char ch = 'd';
return 0;
}
2.4 const_cast(去常量类型转换)
1 常用于去除const对象的只读属性
2.并且强制的转换类型必须是指针*或者引用&,不能是普通数据类型
int main()
{
const int i =2;
const int& j = 2;
int& p = const_cast<int&>(j);
int* p2 = const_cast<int*>(&j);
//不能转换成普通的数据类型
// int k = const_cast<int>(j); //error
return 0;
}