红魔咖啡馆

头发越掉越多,头发越掉越少

0%

【C++】类型转换

类型转换

隐式转换

要求:相互转换的类型兼容

当一个值被赋值到另一个兼容类型时,会自动发生隐式转换

但这样会造成精度损失

类对象之间也可以发生隐式转换

1
2
SubClass* pSub = new SubClass();
BaseClass* pBase = pSub;

如上是将子类指针转换为了基类指针,这是常用的类指针间的隐式转换

若上方SubClassBaseClass之间没有继承关系,他们的指针是无法进行隐式转换的

除非重载运算符或构造函数

1
2
3
4
class classA{};
class classB{
    public: ClassB (const ClassA& a){}
};

这种方法类似于拷贝构造,但参数类型不同,我们称这种为转换构造函数

显式转换

使用变量类型运算符

1
2
int a = 2;
float b = (float)a // 或float(a)

以上将整型a转化为了浮点数

1
2
SubClass obj;
BaseClass* pBase = (BaseClass*) &obj;

以上将子类对象obj的地址转换成了基类的指针,但若两者没有继承关系,则转换时可能会访问到奇怪的位置

动态转换

语法:dynamic_cast <转换类型> (表达式)

只能用于对象的指针和引用的转换

用于多态类的向下转换(向上转换一定可以成功,故可以直接使用普通类型转换)

dynamic_cast进行两个阶段的检查:

  • 编译阶段:检查基类是否是多态类,不是会报错
  • 运行阶段:检查转换对象是派生类对象,不是会返回空指针

动态转换需要RTTI

1
2
3
4
5
6
7
class CBase{
};
class CDerive: public CBase{};

CBase obj;
// 基类不是多态类,无法转换
CDerive *ptr = dynamic_cast<CDerived*>(&obj);
1
2
3
4
5
6
7
8
9
class CBase{
public:
    virtual ~CBase(){}
};
class CDerive: public CBase{};

CBase obj;
// 不是派生类对象,转换失败
CDerive *ptr = dynamic_cast<CDerived*>(&obj);

静态转换

语法:static_cast <转换类型> (表达式)

可用于基类到派生类的向下转换与派生类到基类的向上转换

static_cast只进行编译阶段的检查:检查两个类是否兼容(不要求基类是多态类)

静态转换可以替代隐式转换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class CBase{};
class CDerive: public CBase{};

class COther{};

CBase *p;
CDerive *p1;
COther other;
CDerive obj;
// 
p = static_cast<CBase*>(&obj);
p1 = static_cast<CDerive*>(&obj);

// 会提示类型转换无效
p = static_cast<CBase*>(&other);
p1 = static_cast<CDerive*>(&other);

重解释转换

语法:reinterpret_cast <转换类型> (表达式)

用于类指针之间的转换,而不会检查类型是否有效

也可用于整型与指针间的转换(注意整型的数据范围能容纳指针数值)

应用:

  • 与内存和硬件直接交互的底层与接口程序
  • 与操作系统组件交互
  • 处理网络或多媒体数据
1
2
3
4
5
6
7
8
9
10
class CBase{};
class CDerive: public CBase{};

class COther{};

CBase *p;
CDerive *p1;
COther other;
p1 = reinterpret_cast<CDerive*>(0xEFL);
long long address = reinterpret_cast<long long>(&other);

常量转换

语法:const_cast &lt;转换类型&gt; (表达式)

用于常量与非常量之间的转换,转换类型必须是指针或引用

应用:

  • 在调用不修改对象但未声明常量参数的函数时,暂时取消对象的常量类型
  • 临时取消对象中的const属性,以便调用成员函数修改其中成员
1
2
3
4
5
int hello(char* str){
    cout <<str<<endl;
}
const char* str = "world!";
hello(const_cast<char*>(str));

注意,进行转换不意味着可以进行修改