一、先说C语言,C语言中有两种类型转化:
(1)隐式转化
int i;
float j = i;
(2)显式转化
void *p;
int *a = (int*)p
二、谈一谈C++中的两种标准类型转化:static_cast、dynamic_cast
C++作为C语言的扩展仍然支持C语言中原有的类型转化方式,但是由于多加了“类“,所以C++对于类型转化需要更高的安全保障。
C++中共有四种标准类型转化:(static_cast,dynamic_cast,const_cast,reinterpret_cast)
(1)static_cast,发生在编译期
a)在进行基本数据类型(int, float...)之间的转化时的效果和显示转化的效果相同
float i = 2.1;
int j = (int)i;
int j = static_cast<int>(i);
<span style="font-family: Arial, Helvetica, sans-serif;">输出后都为:2</span>
b)基类与子类之间指针的类型转化,使用static_cast可以在一个继承树内自由转化,没有关系的两个类指针之间的转化会报错
上行转化:子类-->基类(安全)
下行转化:基类-->子类(不安全)
class A {};
class B {};
class C:public B{}
B *b;
A *a = static_cast<A*>b; //会直接报错,因为A和B之间并没有关系
C *c = static_cast<C*>b; //不会报错,但是这种转化不安全,因为b可能只是B的指针
(2)dynamic_cast,发生在运行期
这是C++为了保证向下的类型转化安全而设置的转化方式。
使用dynamic_cast动态转化要求类中必须有虚函数,因此我觉得dynamic转化是根据虚函数表来确定转化类型是否安全的。
使用dynamic_cast转化,它会在运行期间进行类型转化,如果目标类型和源类型不是同一类型,则返回null值。
class People
{
virtual void fun()
{
std::cout<<"People::fun"<<std::endl;
}
}
class Student:public <span style="font-family:Arial, Helvetica, sans-serif;">People</span>
{
void fun()
{
std::cout<<"Student::fun"<<std::endl;
}
}
class Teacher:pubic <span style="font-family: Arial, Helvetica, sans-serif;">People</span>
{
void fun()
{
std::cout<<"Teacher::fun"<<std::endl;
}
}<pre name="code" class="cpp">class Other {
public:
virtual void func()
{
cout<<"Other::func()"<<endl;
}
};
using namespace std;
int main(void)
{
People *pe = new Student;
Teacher* dy_te = dynamic_cast<Teacher*>(pe);
Teacher* st_te = static_cast<Teacher*>(pe);
cout << "dy_te: " << dy_te << endl;
cout << "st_te: " << st_te << endl;// dy_te->fun(); //pe绑定的是Student而不是Teacher,dy_te为0,调用此句会失败
st_te->fun(); // pe绑定的是Student而不是Teacher,st_te不识别这些, 而是当做red的函数来处理!
Other* _other = new Other;
Teacher* dy_tee = dynamic_cast<Teacher*>(_other);//
Teacher* st_tee = static_cast<Teacher*>(_other);// _other绑定的是other而不是Teacher,编译的时候失败
Teacher* t = (Teacher*)_other; t->fun();
cout << "t: " << t << endl;
cout << "dy_tee"<< dy_tee << endl;
delete pe; delete _other;
pe = NULL;
_other = NULL;
return 0;
}
终端输出的值如下:
dy_te: 0x0
st_te: 0x100105510
Stuent::fun()
Other::func()
t: 0x100105520
dy_tee: 0x0
参考了另一篇博客http://windsplife.blogspot.com/2010/09/cstaticcast-dynamiccast-reinterpretcast.html后发现dynamic_cast还可以抛出std::bad_cast异常
其具体例子如下:
#include <iostream>
#include <typeinfo>
using namespace std;
class Base {
public:
virtual void foo() = 0;
};
class Derived1 : public Base {
public:
void foo() {
cout << "Derived1" << endl;
}
void showOne() {
cout << "Yes! It's Derived1." << endl;
}
};
class Derived2 : public Base {
public:
void foo() {
cout << "Derived2" << endl;
}
void showTwo() {
cout << "Yes! It's Derived2." << endl;
}
};
void showWho(Base &base) {
try {
Derived1 derived1 = dynamic_cast<derived1&>(base);
derived1.showOne();
}
catch(bad_cast) {
cout << "bad_cast 轉型失敗" << endl;
}
}
int main() {
Derived1 derived1;
Derived2 derived2;
showWho(derived1);
showWho(derived2);
return 0;
}
注: 在<Google C++代码规范>中, google内部约定: 除单元测试外, 不要使用 dynamic_cast, 如果你需要在运行时确定类型信息, 说明设计有缺陷 .
具体的讨论可参见:http://www.zhihu.com/question/22445339
完成这篇文章参考了以下资料:
http://www.cnblogs.com/weidagang2046/archive/2010/04/10/1709226.html
http://stackoverflow.com/questions/332030/when-should-static-cast-dynamic-cast-const-cast-and-reinterpret-cast-be-used
http://blog.sina.com.cn/s/blog_5a48dd2d0101cnzr.html
剩下的两种标准类型转化将会在以后在进行研究。