TheRiver | blog

You have reached the world's edge, none but devils play past here

0%

c++11四种cast转换

参考

C++类型转换

四种类型转换(cast)的关键字 详解 及 代码

C ++中的static_cast 类型转换运算符

C ++中的dynamic_cast和static_cast


const_cast

const_cast用于移除类型的const、volatile和__unaligned属性。

const int a = 1;
int *b = const_cast<int*>(&a);

int c = 1;
const int *d = const_cast<const int *>(&c);

注意点

如果变量原来是const类型的常量,新的指针或引用是非常量,解除const限定后再去修改值是未定义的行为,const_cast只是用于修改变量的const属性,使用者应该考虑清楚操作的安全性.

INPUT

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

int main() {

const int a = 1;
int *b = const_cast<int*>(&a);
*b = 2;

cout << a << endl;
cout << *b << endl;

cout << &a << endl;
cout << b << endl;

}

OUTPUT

1
2
0139F748
0139F748

static_cast

static_cast< Type* >(ptr)

This takes the pointer in ptr and tries to safely cast it to a pointer of type Type*. This cast is done at compile time. It will only perform the cast if the type types are related. If the types are not related, you will get a compiler error.

主要用在:

  • 类的上行转换(派生类转基类,public继承),下行转换是不安全的,需要编码时确认清楚
  • 基本数据类型的转换(int,char,double),安全性需要编码时确认
  • 将void指针转换成非void指针

数据类型转换

INPUT

1
2
3
4
5
6
7
8
9
10
11

#include <iostream>
using namespace std;
int main()
{
float f = 3.5;
int a = f; // this is how you do in C
int b = static_cast<int>(f);
cout << b;
}

OUTPUT

3

指针类型转换

INPUT

1
2
3
4
5
6
7
8
9
10
11
12
13
14

#include <iostream>
using namespace std;
int main()
{
int a = 10;
char c = 'a';

// pass at compile time, may fail at run time
int* q = (int*)&c; //c语言可以
int* p = static_cast<int*>(&c); //c++的失败
return 0;
}

OUTPUT

错误 C2440 “static_cast”: 无法从“char *”转换为“int *” test


空指针

1
2
3
4
5
6
7
8
9
10

#include <iostream>
int main()
{
int i = 10;
void* v = static_cast<void*>(&i);
int* ip = static_cast<int*>(v);
return 0;
}


类对象转换

INPUT

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

#include <iostream>
using namespace std;
class Base {
};
class Derived : private Base { // Inherited private/protected not public
};
int main()
{
Derived d1;
Base* b1 = (Base*)(&d1); // allowed
Base* b2 = static_cast<Base*>(&d1);
return 0;
}

OUTPUT

错误(活动) E0269 不允许对不可访问的基类 “Base” 进行转换 test

**:**上行转换的时候,一定要是public继承,private/protected都会编译报错


dynamic_cast

dynamic_cast< Type* >(ptr)

以下拷贝自:链接

This again tries to take the pointer in ptr and safely cast it to a pointer of type Type*. But this cast is executed at runtime, not compile time. Because this is a run-time cast, it is useful especially when combined with polymorphic classes. In fact, in certian cases the classes must be polymorphic in order for the cast to be legal.

Casts can go in one of two directions: from base to derived (B2D) or from derived to base (D2B). It’s simple enough to see how D2B casts would work at runtime. Either ptr was derived from Type or it wasn’t. In the case of D2B dynamic_cast<>s, the rules are simple. You can try to cast anything to anything else, and if ptr was in fact derived from Type, you’ll get a Type* pointer back from dynamic_cast. Otherwise, you’ll get a NULL pointer.

But B2D casts are a little more complicated. Consider the following code:

INPUT

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
48

#include <iostream>
using namespace std;

class Base
{
public:
virtual void DoIt() = 0; // pure virtual
virtual ~Base() {};
};

class Foo : public Base
{
public:
virtual void DoIt() { cout << "Foo"; };
void FooIt() { cout << "Fooing It..."; }
};

class Bar : public Base
{
public :
virtual void DoIt() { cout << "Bar"; }
void BarIt() { cout << "baring It..."; }
};

Base* CreateRandom()
{
if( (rand()%2) == 0 )
return new Foo;
else
return new Bar;
}


int main()
{
for( int n = 0; n < 10; ++n )
{
Base* base = CreateRandom();

base->DoIt();

Bar* bar = (Bar*)base;
bar->BarIt();
}
return 0;
}

OUTPUT

Bar
baring It...
---------------
Bar
baring It...
---------------
Foo
baring It...
---------------
Foo
baring It...
---------------
Bar
baring It...
---------------
Foo
baring It...
---------------
Foo
baring It...
---------------
Foo
baring It...
---------------
Foo
baring It...
---------------
Foo
baring It...
---------------

main() can’t tell what kind of object CreateRandom() will return, so the C-style cast Bar* bar = (Bar*)base; is decidedly not type-safe. How could you fix this? One way would be to add a function like bool AreYouABar() const = 0; to the base class and return true from Bar and false from Foo. But there is another way: use dynamic_cast<>:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

int main()
{
for( int n = 0; n < 10; ++n )
{
Base* base = CreateRandom();

base->DoIt();

Bar* bar = dynamic_cast<Bar*>(base);
Foo* foo = dynamic_cast<Foo*>(base);
if( bar )
bar->BarIt();
if( foo )
foo->FooIt();
}
return 0;

}

The casts execute at runtime, and work by querying the object (no need to worry about how for now), asking it if it the type we’re looking for. If it is, dynamic_cast<Type*> returns a pointer; otherwise it returns NULL.

In order for this base-to-derived casting to work using dynamic_cast<>, Base, Foo and Bar must be what the Standard calls polymorphic types. In order to be a polymorphic type, your class must have at least one virtual function. If your classes are not polymorphic types, the base-to-derived use of dynamic_cast will not compile. Example:

1
2
3
4
5
6
7
8
9
10
11
12
13

class Base {};
class Der : public Base {};


int main()
{
Base* base = new Der;
Der* der = dynamic_cast<Der*>(base); // ERROR - Won't compile

return 0;
}

Adding a virtual function to base, such as a virtual dtor, will make both Base and Der polymorphic types:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

class Base
{
public:
virtual ~Base(){};
};
class Der : public Base {};


int main()
{
Base* base = new Der;
Der* der = dynamic_cast<Der*>(base); // OK

return 0;
}


reinterpret_cast

reinterpret_cast is a type of casting operator used in C++.

  • It is used to convert one pointer of another pointer of any type, no matter either the class is related to each other or not.
  • It does not check if the pointer type and data pointed by the pointer is same or not.

syntax:

data_type *var_name = 
    reinterpret_cast <data_type *>(pointer_variable);

Return Type:

It doesn’t have any return type. It simply converts the pointer type.

Purpose for using reinterpret_cast:

1 reinterpret_cast is a very special and dangerous type of casting operator. And is suggested to use it using proper data type i.e., (pointer data type should be same as original data type).

2 It can typecast any pointer to any other data type.

3 It is used when we want to work with bits.

4 If we use this type of cast then it becomes a non-portable product. So, it is suggested not to use this concept unless required.

5 It is only used to typecast any pointer to its original type.

6 Boolean value will be converted into integer value i.e., 0 for false and 1 for true.

谷歌翻译

1 reinterpret_cast是一种非常特殊且危险的类型转换操作符。建议使用它的时候要是合适的数据类型(指针数据类型应与原始数据类型相同)

2 它可以将任何指针类型转换为任何其他数据类型

3 当我们要使用位时使用

4 如果我们使用这种类型的演员表,那么它将成为不可携带的产品。因此,建议除非必要,否则不要使用此概念

5 它仅用于将任何指针转换为原始类型

6 布尔值将转换为整数值,即0代表false和1代表true


总结

static_cast,const_cast转换指针类型都会在编译期报错,这比c语言那种显示类型转换要安全

const_cast修改最初声明为const的值是未定义的行为

static_cast上行转换的时候,继承方式需要是public

dynamic_cast运行期转换,向下转换是安全的(会抛出异常或返回空指针),但是向下转换的时候基类必须是多态的


ending

76654577_p0_lit.jpg

----------- ending -----------