
[toc]
强制类型转换
static_cast
用于基本数据类型之间的转换,以及在类层次结构中基类和派生类之间的指针或引用的转换。它在编译时执行,不提供运行时类型检查。
如果对象所属的类重载了强制类型转换运算符 T(如 T 是 int、int* 或其他类型名),则 static_cast 也能用来进行对象到 T 类型的转换。
static_cast 不能用于在不同类型的指针之间互相转换,也不能用于整型和指针之间的互相转换,当然也不能用于不同类型的引用之间的转换。因为这些属于风险比较高的转换。
例:
1 | int a = 10; |
dynamic_cast
用于类层次结构中的指针和引用的转换,它在运行时检查类型的安全性。它要求转换的类型必须包含至少一个虚函数。
如果转换失败,dynamic_cast会返回nullptr。
例:
1 | class Base {}; |
dynamic_cast
与reinterpret_cast
的区别:
- 用 reinterpret_cast 可以将多态基类(包含虚函数的基类)的指针强制转换为派生类的指针,但是这种转换不检查安全性,即不检查转换后的指针是否确实指向一个派生类对象。
- dynamic_cast专门用于将多态基类的指针或引用强制转换为派生类的指针或引用,而且能够检查转换的安全性。对于不安全的指针转换,转换结果返回 nullptr 指针。
const_cast
仅用于去除变量的const属性。它主要用于操作指向常量对象的指针或引用的const属性。
例:
1 | const int a = 10; |
reinterpret_cast
用于低级的强制类型转换,如改变指针类型或将指针转换为足够长度的整型。它仅仅复制位模式,不改变值本身。
[!warning]
这种转换是不安全的,因为它不保证转换结果的有效性:
例如,执意把一个 int* 指针、函数指针或其他类型的指针转换成 string* 类型的指针也是可以的,至于以后用转换后的指针调用 string 类的成员函数引发错误,则需要程序员自行承担查找错误的烦琐工作
例:
1 | int* a = new int; |
函数指针
函数指针的定义:
1 | // 注意 func_pointer只是一个指向特定类型函数的指针,并不是一个函数。要指向哪个函数就将哪个函数赋值给它 |
举个例子:
1 | int test(int a) |
typedef简化函数指针的定义
参见:简化函数指针的定义
指向类成员函数的函数指针
形如:int (A::*p)(void)
的函数指针只能指向class A
的非静态成员函数,并且调用时必须通过对象提供this
指针。原因:含有A::
,指向一个需要特定对象才能调用的函数。
形如:int (*p)(void)
的函数指针,如果要指向类内的函数,则只能指向类内的static
函数,并且可以直接通过p()
调用。原因:看形式就知道是一个普通函数指针,而普通函数指针不需要特定对象就可以调用。
指向**非静态(non static)**成员函数的函数指针
1 | class A { |
指向**静态(static)**成员函数的函数指针
1 |
|
typedef的四种用法
基本数据类型的别名
1 | typedef int INTEGER; // 为int类型定义别名INTEGER |
自定义数据类型的别名
1 | typedef class test{ // 这里将class换成struct效果一样 |
给数组类型取别名
假设这么一种情况:我需要定义 10 个长度为 100 的int
类型数组。最简单的是下面这种方法:
1 | int arr_1[100]; int arr_2[100]; |
可见需要写10个数组的定义。
除了上面的方法,还可以用另一种方法快速定义10个数组。
1 | typedef int ARR_LENGTH_100[100]; |
虽然也是写了10个数组的定义,不过要比上一个简洁的多。
简化函数指针的定义
需要先了解:[函数指针](# 函数指针)
假设我们需要定义2个函数指针,这两个函数指针指向的函数类型相同。正常来说是写两句:
1 | int (*fp1)(int, char); |
那么假设需要定义5个呢?10个呢?总不能复制粘贴10行吧。
这时候就可以用typedef
了:
1 | int test(int a, char ch) { |
这样就可以一次性定义多个函数指针了。当然得是同类型的才行
这还没完,我们甚至可以定义一个函数指针数组。数组里面每个元素都是指向一个函数的函数指针。
1 | void t1(){cout<<"test1"<<endl;} |
这样也可以一次性定义多个函数指针,并且更加便捷。
typedef
与#define
的区别
本质:typedef
是定义别名,而#define
是简单的字符串替换
可以使用其他类型说明符对宏类型名(由
#define
定义)进行扩展,但对typedef
所定义的类型名却不能这样做。1
2
3
4
5
unsigned INTERGE n; //没问题
typedef int INTERGE;
unsigned INTERGE n; //错误,不能在 INTERGE 前面添加 unsigned在连续定义几个变量的时候,
typedef
能够保证定义的所有变量均为同一类型,而#define
则无法保证。#define
1
2
3
4
5
PTR_INT p1, p2;
// 经过宏替换后,p1, p2变为:
int *p1, p2; // p1是int类型的指针变量。p2是int类型的整数变量typedef
1
2typedef int * PTR_INT
PTR_INT p1, p2;