1、应用场景
class Base{};
class Derived : public Base{};
Base* b = new Derived();
语法很简单,但是背后的原理需要弄明白,这里重新回顾一下 Base *b = new Derived();这一行代码。是父类指针指向子类对象,那么内存会发生什么呢。首先要明白子类的内存布局,当子类继承父类的时候,子类对象内存布局首先是父类的内存空间,然后是子类新增的数据成员。
而“父类指针指向子类”这一操作,Base*指向的是子类对象中父类部分的起始地址,也就是说,父类指针只“看得见”子类对象中属于父类的部分。
在这个例子中,Base* b
指向的是 Derived
对象的基类部分,虽然实际对象是 Derived
,但通过 b
只能访问基类的数据成员和函数。如果基类有虚函数,通过基类指针调用虚函数时,会正确地调用派生类中覆盖的虚函数(对于虚函数指针来说,子类会进行重覆盖,所以"只能访问基类的数据成员和函数"这一项不包含虚函数指针,虚函数指针对于b来说也是可以看得见的。),这是多态的实现原理。
注意,这个“看的见”的概念很重要,现在有一个场景,子类中定义了一个变量derived_data,那么父类该怎么访问这个变量?因为父类对象b是先不见子类的成员变量derived_data的,想要访问只能进行向下类型转换,这个时候就需要用到static_cast或者dynamic_cast
Base* b = new Derived(); // b 是 Base* 类型
Derived* d = static_cast<Derived*>(b); // 将 Base* 转换为 Derived*
d->derived_data = 10; // 现在可以访问 derived_data
2、static_cast
static_casty是一种编译时的类型转换,它用于进行静态类型检查。它不会在运行时检查转换是否安全,只是根据类型规则在编译时进行转换。
class Base{};
class Derived : public Base{};
Base* b = new Derived();
Derived* d = static_cast<Derived*>(b);
3、dynamic_cast
相比较static_cast,是一种运行时的类型转换,通常用于类之间的指针或者引用转换。可以执行运行时类型检查,确保转换是安全的。需要类中至少有一个虚函数,以便在运行时通过虚函数表检查类型。
4、const_cast
作用:用于删除或添加对象的const修饰符,主要用于将常量对象转换为非常量对象。