# 继承和dynamic\_cast

## 本章节目前有较多纰漏, 请暂时无视本章, 笔者还在查资料

我们前面已经讲解了关于虚表和虚类的继承, 这样我们讲解dynamic\_cast就方便许多了

首先我们要划定一下dynamic\_cast的用途范围

笔者刚开始接触这个模板函数的时候, 曾经以为他会影响成员变量之类的东西

实际上这个函数只会操作一个东西, 那就是虚表地址, 他只会替换虚表地址为需要cast的类型的地址

在详细讲解这一切之前, 笔者还是想从别的东西作为切入点

笔者想从class这个关键字的本质含义讲起

class的本质其实是定义了一个任意字节宽度的类型

而继承就是按顺序拼接各个类的字节

可以运行以下例子

```
#include <iostream>
using namespace std;
class A {
public:
    int a;
    A() {
        a = 1;
    }
};
class B {
public:
    int b;
    B() {
        b = 2;
    }
};
class C:public A,public B {
public:
    int c;
    C() {
        c = 3;
    }
};

class D :public B, public A {
public:
    int d;
    D() {
        d = 4;
    }
};

int main()
{
    A* c1 = new C;
    B* c2 = new C;

    A* d1 = new D;
    B* d2 = new D;
    
    cout << c1->A::a << " " << c2->b << " " << d1->a << " " << d2->b << " ";

}
```

以c1和c2为例

他们的类型不同, 调用相同的new函数, 但是返回的地址不同:

![](https://2725818927-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHXAJ4vJc9Xj8I4m4bgu6%2Fuploads%2FzdHy2O5KJI4Ax7G7xWkc%2Fimage.png?alt=media\&token=d4958db8-948e-43e3-a0fe-de14cdd5506f)

![](https://2725818927-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHXAJ4vJc9Xj8I4m4bgu6%2Fuploads%2F35BygAw2tHwPznLU95ko%2Fimage.png?alt=media\&token=3bb4a9a0-a24d-4745-8c78-cf920b77a06c)

![](https://2725818927-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHXAJ4vJc9Xj8I4m4bgu6%2Fuploads%2F8X4COVVsdiWb0qpsi05V%2Fimage.png?alt=media\&token=c334e503-0f04-44bc-a2a9-04833beaa863)

可以看到c2的偏移往后移动了4字节

笔者目前还没仔细了解这个字节偏移是谁实现的, 猜测是new运算符里面实现的

但是总的来说, 继承就是按顺序把不同域的成员拼接起来, 然后把虚表替换一下

对于成员来说, 他们的结构顺序可以静态确定, 并且在new的动态过程中, 可以保证指针域只会包含静态类型所覆盖的范围, 动态类型的范围可以安全的不被所指

也就是说, 动态类型为X的, 静态类型为Y(也就是说Y是基类)的一个对象(不论有没有虚函数), 可以被安全的静态转换为 动态和静态类型均为X的对象

但是如果要将上面的对象转换为动态类型和静态类型均为Y的对象, 则不可以安全的通过静态转换(static\_cast 或 c-like的括号强制转换)实现

形象一点来说

以C-like方式在C++的继承结构中, 向上移动是安全的(图源[g4g](https://www.geeksforgeeks.org/cpp-hierarchical-inheritance/))

![](https://2725818927-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHXAJ4vJc9Xj8I4m4bgu6%2Fuploads%2F5UHFtpyWwbnTITRVTdAj%2Fimage.png?alt=media\&token=bb9f649e-46fe-4011-beb9-49478a8cbfff)

但是向下移动是不安全的

~~因为虚函数的工程含义是, 用继承树上的most delivered node的虚表中的函数实现, 代替基类的实现~~

### 参考文档

{% embed url="<https://www.ibm.com/docs/en/zos/2.4.0?topic=expressions-dynamic-cast-operator-c-only>" %}

{% embed url="<https://stackoverflow.com/questions/4644753/c-dynamic-cast-polymorphic-requirement-and-downcasting>" %}
