类型转换 C++11

一、static_cast

C++11提供了四种适用于不同场景的强制类型转换函数:

  • static_cast 静态转换
  • dynamic_cast 动态转换
  • const_cast 常量转换
  • reinterpret_cast 重解释转换

#include <iostream>

using namespace std;

int main()

{

double x = 1.1;

// double → int

int i = static_cast<int>(x);

cout << i << endl;

return 0;

}

static_cast没有运行时类型检查来保证转换的安全性,需要程序员判断转换是否安全。

static_cast还可以用于类层次结构中,即基类和派生类指针或引用的转换,但是还需要注意:

  • static_cast进行上行转换是安全的,即把派生类指针或引用转换为基类的;
  • static_cast进行下行转换是不安全的,即把基类指针或引用转换为派生类的;

基于指针的转换: 

#include <iostream>

using namespace std;

class Animal

{

public:

string a = "Animal";

};

class Monkey:public Animal

{

public:

string b = "Monkey";

};

int main()

{

// 上行转换

Monkey* s1 = new Monkey;

Animal* f1 = static_cast<Animal*>(s1);

cout << f1->a << endl;

Animal* a1 = new Animal;

cout << sizeof(*f1) << " " << sizeof(*a1) << endl; // 4 4

cout << sizeof(*s1) << endl; // 8

cout << s1 << " " << f1 << endl; // 0x861048 0x861048

// 下行转换

Animal* f2 = new Animal;

Monkey* m2 = static_cast<Monkey*>(f2);

cout << m2->a << " " << m2->b << endl; // Animal 乱码

return 0;

}

基于引用的转换:

#include <iostream>

using namespace std;

class Animal

{

public:

string a = "Animal";

};

class Monkey:public Animal

{

public:

string b = "Monkey";

};

int main()

{

// 上行转换

Monkey m1;

Animal& a1 = static_cast<Animal&>(m1);

cout << a1.a << endl;

a1.a = "hahah";

cout << m1.a << endl; // hahah

// 下行转换

Animal a2;

Monkey& m2 = static_cast<Monkey&>(a2);

// 结果仍然不是想要的结果

cout << m2.a << " " << m2.b << endl; // Animal hahah

return 0;

}

static_cast可以用于对象创建,但是参数必须与目标对象的构造函数相同。

#include <iostream>

using namespace std;

class Student

{

private:

string name;

public:

Student(string name):name(name){}

string get_name() const

{

return name;

}

};

int main()

{

Student s = static_cast<Student>("Tom");

cout << s.get_name() << endl; // Tom

return 0;

}

 二、dynamic_cast

dynamic_cast主要用于类层次之间的上行转换和下行转换。

  • 上行转换与static_cast效果相同。
  • 下行转换具有类型检查的功能,比static_cast更安全。

#include <iostream>

using namespace std;

class Animal

{

public:

string a = "Animal";

virtual void eat()

{

cout << "吃东西" << endl;

}

};

class Monkey:public Animal

{

public:

string b = "Monkey";

virtual void eat()

{

cout << "吃香蕉" << endl;

}

};

int main()

{

Animal* a0 = new Monkey;

Monkey* m0 = dynamic_cast<Monkey*>(a0);

cout << m0->a << " " << m0->b << " " << endl;

m0->eat();

Monkey m1;

Animal& a1 = m1;

Monkey& m2 = dynamic_cast<Monkey&>(a1);

// m2就是m1的引用

cout << m2.a << " " << m2.b << endl;

m2.eat();

return 0;

}

三、const_cast

         const_cast可以用于添加或移除对象(通常是指针或引用)的const修饰符。在正常情况下,应该尽量避免使用const_cast,而是考虑通过设计良好的接口或者其他手段来避免这样的转换。

#include <iostream>

using namespace std;

class Animal

{

public:

string a = "Animal";

};

int main()

{

const Animal* ani = new Animal;

// ani->a = "动物"; 错误

Animal* ani2 = const_cast<Animal*>(ani);

cout << ani << " " << ani2 << endl; // 0xf71048 0xf71048

ani2->a = "动物";

cout << ani->a << " " << ani2->a << endl; // 动物 动物

return 0;

}

四、reinterpret_cast

reinterpret_cast可以把内存里的值重新解释,这种转换的风险极高,慎用!

#include <iostream>

using namespace std;

class Deer

{

public:

void print()

{

cout << "我是鹿" << endl;

}

};

class Horse

{

public:

string shoes = "铁蹄";

void print()

{

cout << "我是马" << endl;

}

};

int main()

{

Deer *d = new Deer;

Horse* h = reinterpret_cast<Horse*>(d);

cout << d << " " << h << endl; // 0x1011048 0x1011048

h->print();

// cout << h->shoes << endl; // 乱码(强制拓展内存导致)

char c = '%';

char* c_ptr = &c;

int* i_ptr = reinterpret_cast<int*>(c_ptr);

// 虽然保存的是字符'%',但是用int的方式解读

cout << *i_ptr << endl; // 很大的数(强制拓展内存导致)

return 0;

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值