用法:
它主要有如下几种用法:
对于static_cast,上行转换时安全的,而下行转换时不安全的
因为static_cast的转换时粗暴的,它仅根据类型转换语句中提供的信息(尖括号中的类型)来进行转换,这种转换方式对于上行转换,由于子类总是包含父类的所有数据成员和函数成员,因此从子类转换到父类的指针对象可以没有任何顾虑的访问其(指父类)的成员。
而对于下行转换为什么不安全,是因为static_cast只是在编译时进行类型检查,没有运行时的类型检查,具体原理在dynamic_cast中说明。
用法:
【格式】dynamic_cast<type_id>(expression) :
该运算符把expression转换为type_id 类型, type_id 可以为类的指针、类的引用、void*,expression为对应的指针或引用.
dynamic_cast,主要用于类层次间的转换:
上行转换(子类转父类),转换安全,成功返回类对象指针, 此时和static_cast 作用一样。
下行转换(父类转子类), 父类中要有虚函数,否则编译器报错。转换分几种情况:
a. 父类指针指向子类对象,转换安全, dynamic_cast返回类对象指针。
b.父类指针指向父类对象,转换不安全,dynamic_cast 返回nullptr。
此时若使用static_cast, 返回非空指针,更不安全。
eg:
#include
using namespace std;
class A{
public:
A(){}
virtual void eat()
{
std::cout<<"A::eat()"<<std::endl;
}
void sing(){
std::cout<<"A::sing()"<<std::endl;
}
~A(){};
};
class B : public A{
public:
B() {};
void eat()
{
std::cout<<"B::eat()"<<std::endl;
}
void sing()
{
std::cout<<"B::sing()"<<std::endl;
}
~B(){}
int data;
};
int main()
{
A* a= nullptr;
B* b = nullptr;
A aa;
B bb;
b = &bb;
// 安全的向上转型
a = dynamic_cast<A*>(b);
a->sing();
a->eat();
std::cout<<"===="<<std::endl;
// 向下转型,向下转型时,父类必须含有虚函数,否则编译报错
//父类指针指向子类对象,这样的dynamic_cast向下转换才是安全的
a = &bb;
b = dynamic_cast<B*>(a);
b->sing();//yes
b->eat();//yes
std::cout<<"===="<<std::endl;
//父类指针指向父类对象,这样的dynamic_cast向下转换是不安全的
a = &aa;
b = dynamic_cast<B*>(a);
if (b == nullptr)
{
std::cout<<"the call is not safe "<<std::endl;
}
b->sing();//yes
b->eat();//Segmentation fault
std::cout<<"===="<<std::endl;
//static_cast不做类型检查,不返回nullptr,不安全
b = static_cast<B*>(a);
if (b == nullptr)
{
std::cout<<"second the call is not safe "<<std::endl;
}
b->sing();//yes
b->eat();//居然调用的基类的eat,不对
return 0;
}