C++中的类型转换——static_cast dynamic_cast

原文链接:https://blog.csdn.net/baidu_35679960/article/details/80821222

1、隐式转型(向上转型,即将派生类对象赋值给基类)
C++允许向上转型,即将派生类的对象赋值给基类的对象是可以的,其只不过是将派生类中基类的部分直接赋给基类的对象,这称为向上转型(此处的“上”指的是基类),例如:

class Base{ };
class Derived : public base{ };
Base* Bptr;
Derived* Dptr;
Bptr = Dptr; //编译正确,允许隐式向上类型转换
Dptr = Bptr;//编译错误,C++不允许隐式的向下转型;

但是编译正确不代表能够使得程序安全运行。这很好理解,如果你把一个指向Base类对象的指针 赋值 给一个Drived类类型的指针,如果这个指针去访问Drived类中存在而Base类中不存在成员,很明显就不安全了。
所以一个更好的办法是使用dynamic_cast;

2、向下转型
正如上面所述,类层次间的向下转型是不能通过隐式转换完成的。此时要向达到这种转换,可以借助static_cast 或者dynamic_cast。

2.1 通过static_cast完成向下转型
例如:

class Base{ };
class Derived : public base{ };
Base* B;
Derived* D;
D = static_cast<Drived*>(B); //正确,通过使用static_cast向下转型

需要注意的是:static_cast的使用,当且仅当类型之间可隐式转化时,static_cast的转化才是合法的。有一个例外,那就是类层次间的向下转型,static_cast可以完成类层次间的向下转型,当时向下转型无法通过隐式转换完成!

2.2 通过dynamic_cast完成向下转型
和static_cast不同,dynamic_cast涉及运行时的类型检查。如果向下转型是安全的(也就是说,如果基类指针或者引用确实指向一个派生类的对象),这个运算符会传回转型过的指针。如果downcast不安全(即基类指针或者引用没有指向一个派生类的对象),这个运算符会传回空指针。
ps:要使用dynamic_cast类中必须定义虚函数

class Base{
publicvirtual void fun(){}
};
class Drived : public base{
public:
int i;
};
Base *Bptr = new Drived();//语句0
Derived *Dptr1 = static_cast<Derived *>(Bptr); //语句1;
Derived *Dptr2 = dynamic_cast<Derived *>(Bptr); //语句2;

此时语句1和语句2都是安全的,因为此时Bptr确实是指向的派生类,虽然其类型被声明为Base*,但是其实际指向的内容确确实实是Drived对象,所以语句1和2都是安全的,Dptr1和Dptr2可以尽情访问Drived类中的成员,绝对不会出问题。
但是此时如果将语句0改为这样:

Base *Bptr = new Base();


那语句1就不安全了,例如访问Drived类的成员变量i的值时,将得到一个垃圾值。(延后了错误的发现)
语句2使得Dptr2得到的是一个空指针,对空指针进行操作,将发生异常,从而能够尽早的发现错误,这也是为什么说dynamic_cast更安全的原因。

原文地址:https://www.cnblogs.com/Galesaur-wcy/p/15219300.html