DREAM OF TECHNICAL ACHIEVEMENT

0%

C++类型转换详解

说到类型转换我们不得不提起C语言的类型转换,简单粗暴.
Type t = (Type) 123

c++ 类型转换

类型 描述
static_cast 一般的转换
dynamic_cast 通常在基类和派生类之间转换时使用
const_cast 主要针对const的转换
reinterpret_cast 用于进行没有任何关联之间的转换,比如一个字符指针转换为整形数

static_cast

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <iostream>
using namespace std;
// static_cast
class Building{};
class Animal{};
class Cat : public Animal{};
void test1(){
int a = 97;

// 普通类型
char c = static_cast<char>(a);
cout << c << endl;

// 转换具有继承关系的对象指针 父转子
Animal *ani = NULL;
Cat *cat1 = static_cast<Cat *>(ani);

// 转换具有继承关系的对象指针 子转父
Cat * soncat = NULL;
Animal *ani1 = static_cast<Animal *>(soncat);

// 转换具有继承关系的对象引用 父转子
Animal aniobj;
Animal &animal = aniobj;
Cat &cat = static_cast<Cat &>(animal);

// 转换具有继承关系的对象引用 子转父
Cat catobj;
Cat &catref = catobj;
Animal &ani2 = static_cast<Animal &>(catref);

// 基础数据类型指针 错误
// error: static_cast from 'int *' to 'char *' is not allowed
// int *p = NULL;
// char *sp = static_cast<char*>(p);

// 对象指针 错误
// error: static_cast from 'Building *' to 'Animal *', which are not related by inheritance, is not allowed
// Building *bui = NULL;
// Animal *ani = static_cast<Animal *>(bui);

}

int main() {
test1();
return 0;
}

从上面例子可见 static_cast 用于内置的数据类型,还有具有继承关系的指针或者引用

dynamic_cast

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <iostream>
using namespace std;
// static_cast
class Building{};
class Animal{};
class Cat : public Animal{};

void test2(){
int a = 10;

// 基础数据类型
// error: 'char' is not a reference or pointer
// char c = dynamic_cast<char>(a);

// 非继承关系指针
// error: 'Animal' is not polymorphic
// Animal *ani = NULL;
// Building *bui = dynamic_cast<Building *>(ani);

// 具有继承关系指针 父转子
// error: 'Animal' does not refer to a value 父类转子类指针 不安全 禁止转换
// Animal *ani = NULL;
// Cat *cat = dynamic_cast<Cat *>(Animal);

// 具有继承关系指针 子转父
Cat *cat = NULL;
Animal *ani = dynamic_cast<Animal *>(cat);
}
int main() {
test2();
return 0;
}

通过上面例子可以看到 dynamic_cast 只能转换具有继承关系的指针或者引用,在转换前会进行对象类型检查.

只能转换子转换父,为什么呢?

我们首先分析一下为什么不能父转换子.

假设 父有2个成员,子继承父,子拥有父的全部属性和方法.如果父转换到子会出现丢失属性和方法情况.所以为什么dynamic_cast只能子转换父

const_cast

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream>
using namespace std;
//const_cast
void test3(){
// 基础数据类型
int a = 10;
const int &b = a;
int &c = const_cast<int &>(b);
c = 20;
cout << "a:" << a << endl;
cout << "b:" << b << endl;
cout << "c:" << c << endl;

// 指针
const int *p = NULL;
int *p2 = const_cast<int *>(p); // 去除const

int *p3 = NULL;
const int *p4 = const_cast<const int *>(p3); // 添加const

}
int main() {
test3();
return 0;
}

根据上面例子我们可以看出来 const_cast 就是添加去除const用的

reinterpret_cast

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
using namespace std;
// static_cast
class Building{};
class Animal{};
class Cat : public Animal{};
typedef void(*FUNC1)(int, int);
typedef int(*FUNC2)(int, char*);
void test4(){
// 无关的指针类型都可以进行转换
Building *bui = NULL;
Animal *ani = reinterpret_cast<Animal *>(bui);

// 函数指针转换
FUNC1 func1;
FUNC2 func2 = reinterpret_cast<FUNC2>(func1);
}
int main() {
test4();
return 0;
}

通过上面例子可以看出来reinterpret_cast可以转换 无关的指针类型,包括函数指针都可以进行转换

总结

  • 结论1:程序员必须清楚的知道要转变的变量,转换前是什么类型,转换后是什么类型,以及转换后有什么后果.
  • 结论2:一般情况下,不建议类型转换,避免进行类型转换.