🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
## 一.子类型 ### 1.子类型的概念 当该类型 `B` 至少提供了类型 `A` 的行为,就称类型 `B` 是类型 `A` 的子类型。此时,类型 `B` 的对象可以像类型 `A` 的对象那样被使用。 子类型是单向的、不可逆的。 ### 2.子类型常用操作 1. 可以用 `B` 来初始化 `A` 的引用。 2. 可以用 `B` 的地址来初始化指向 `A` 的指针。 3. `B` 可以向 `A` 赋值,也可以初始化 `A` 。 ### 3.继承关系中的子类型 假设有类 `B` 继承 `A`,则: + 不论 `B` 以什么方式继承 `A` , 在 `B` 的成员函数和友元中,可以将 `B` 当做 `A` 使用。 + 当 `B` 以公有或受保护的方式继承 `A` , 在 `B` 的派生类 `C` 中, `C` 的成员函数和友元可以将 `B` 当做 `A` 使用。 + 当 `B` 以公有的方式继承 `A`,则可以在任意地方中, `B` 可以当做 `A` 使用。 从上面的几种情况中可以看出,这种 `B->A` 关系的访问权限与继承关系是一致的,而且会像成员一样继承下去。 只有公有派生类才是基类真正的 **子类型** ,它完整地继承了基类的功能。 需要注意的是,将派生类传递给基类的引用后,引用的地址不是派生类对象的地址,而是派生类对象中,基类部分的地址。指针同理。 #### 例1 假设有下面的定义声明: ```c++ struct A1 { int x_; A1(int x = 1) :x_(x) {} }; struct A2 { int x_; A2(int x = 2) :x_(x) {} }; struct A3 { int x_; A3(int x = 3) :x_(x) {} }; struct B : public A1, public A2, public A3 { int y_; }; ``` 然后我们定义一个对象和一个引用: ```c++ B b; A2 &r = b; ``` 接下来我们对这两个变量取地址: ```c++ cout<<&r<<endl; cout<<&b<<endl; ``` >[test] >0019FF24 >0019FF20 定义成指针也是一样的: ```c++ B b; A2 *p = &b; cout<<p<<endl; cout<<&b<<endl; ``` >[test] >0019FF24 >0019FF20