文章目录
一、内置类型与内置类型
1、隐式类型转换:一般是类型与类型之间关联性大的才能进行转换,如:整形与整形、整形与浮点型。
2、显示类型转换:当有关联但是不大时,不能进行隐式类型转换时,就需要进行显示类型转换了,如:指针与整形,不同类型的指针之间。
3、演示:
//隐式类型转化:整形与整形 整形与浮点型
//显示类型转化:指针与整形 不同指针之间指针
void test01()
{
int a = 10;
double b = 1.1;
char c = 'a';
//整形与整形
a = c;
//整形与浮点型
a = b;
int* p2 = &a;
//int d = p; err
int d = (int)p1;
//指针与指针
//char* cp = p; err
char* cp = (char*)p1;
}
二、内置类型与自定义类型
1、内置类型转换为自定类型:这个能不能转换是通过自定义类型的构造函数决定的。
2、自定义类型转换为内置类型:需要自定义类型进行重载,(不需要写返回类型)operator type(转化的内置类型) () 。
3、演示:
class Base1
{
public:
Base1(int a = 10,int b = 10):_a(a),_b(b)
{}
//用与转化的函数
operator int()
{
return _a + _b;;
}
void Printf()
{
cout << "_a:" << _a << "_b:" << _b << endl;
}
private:
int _a = 10;
int _b = 10;
};
void test02()
{
//内置类型转化为自定义类型
Base1 b = { 1,1 };
//Base1 b = Base1(1,1);
b.Printf();
//自定义类型转化为内置类型
int a = Base1();
//int a = b.operator int();
cout << a << endl;
}
三、内置类型与内置类型
1、自定义类型与自定义类型之间转化:看相互的构造函数,如:普通迭代器转换为const
迭代器。
2、演示:
//声明Base3
class Base3;
class Base2
{
// Base3作为Base2的友元
friend class Base3;
public:
Base2(int a = 1, int b = 1) :_a(a), _b(b)
{}
void Printf()
{
cout << "_a:" << _a << "_b:" << _b << endl;
}
private:
int _a ;
int _b ;
};
class Base3
{
public:
Base3(int c = 2, int d = 2) :_c(c), _d(d)
{}
//实现用Base2构造Base3的构造函数
Base3(const Base2& b2) :_c(b2._a), _d(b2._b)
{}
void Printf()
{
cout << "_c:" << _c << "_d:" << _d << endl;
}
private:
int _c ;
int _d ;
};
void test03()
{
//使用Base2转化为Base3
Base3 b3 = Base2();
//Base3 b3(Base2()); Base2用匿名对象构造Base3
b3.Printf();
}
四、c++标准中的4种类型类型转换
1、c++为什么要有这4种转换
2、 static_cast
(1)介绍
(2)语法格式
T a = static_cast<T(需要转换到的类型)> (b) //由b类型转到a类型
(3)使用
//基本数据类型之间的转换
double pi = 3.14159;
int ip = static_cast<int>(pi); // 将 double 类型的 pi 转换为 int 类型的 ip,并截断小数部分
// 类的向上转换(派生类到基类)
class Base {};
class Derived : public Base {};
Derived d;
Base* b = static_cast<Base*>(&d); // 将 Derived 类型的指针转换为 Base 类型的指针
//类的向下转换(基类到派生类) ,注意:这种类型转换是不安全的
Base* b = new Derived();
Derived* d = static_cast<Derived*>(b); // 将 Base 类型的指针转换为 Derived 类型的指针
3、reinterpret_cast
(1)介绍
(2)语法
与 static_cast
语法格式一样。
(3)使用
//指针类型之间的转换
int* ptr1 = new int(10);
char* ptr2 = reinterpret_cast<char*>(ptr1); // 将 int* 转换为 char*
//指针与整数类型之间的转换
int* ptr = new int(42);
char* addr = reinterpret_cast<uintptr_t>(ptr); // 将 int* 转换为 char*
4、 const_cast
(1)介绍
(2)什么是易变性?
(3)语法格式
与 static_cast
语法格式一样。
(4)使用
移除常量性(常用)
const int a = 10;
int* ptr = const_cast<int*>(&a); // 移除 a 的常量性
*ptr = 20; // 未定义行为,因为 a 实际上是常量
注意:上面的例子展示了 const_cast 的用法,但尝试修改 a 的值是未定义行为,因为 a 是在栈上声明的常量,下面使用才是合理的:
const int* ptrToConst = &someNonConstInt; // someNonConstInt 是 int 类型的非 const 对象
int* ptrToNonConst = const_cast<int*>(ptrToConst);
*ptrToNonConst = 42; // 现在可以安全地修改对象
5、 dynamic_cast
(1)介绍
(2)语法格式
与 static_cast
语法格式一样。
(3)使用
向下转型
class Base {
public:
virtual ~Base() {} // 需要虚析构函数
};
class Derived : public Base {
};
Base* basePtr = new Derived();
Derived* derivedPtr = dynamic_cast<Derived*>(basePtr); // 转换成功
if (derivedPtr != nullptr) {
// ... 使用 derivedPtr
}
delete basePtr;
向上转型
class Base {
public:
virtual ~Base() {} // 需要虚析构函数
};
class Derived : public Base {
};
Derived* derivedPtr = new Derived();
Base* basePtr = dynamic_cast<Base*>(derivedPtr); // 转换成功
delete derivedPtr;
(4)注意: