Polymorphism⚓︎
约 739 个字 3 行代码 预计阅读时间 4 分钟
Subclasses and Subtyping⚓︎
- 类定义类型
- 子类定义子类型 (subtypes)
- 子类的对象可以用在子类型的对象需要的地方(这称为代换 (substitution))
- 子类对象可被赋予子类指针变量
- 子类对象可作为超类的参数
-
公有继承里面包含了代换
- 如果 B xxx A,那么使用 A 的同时也在使用 B,且对于 A 而言是
true
的东西对于 B 而言也是true
- 当心不合法的代换
- 如果 B xxx A,那么使用 A 的同时也在使用 B,且对于 A 而言是
-
对于 B 的派生类 D
D -> B
D* -> B*
D& -> B&
Up-casting⚓︎
-
向上转型(up-casting):将派生类的对象看作是基类的对象,是一种将派生类引用或指针转换为基类引用或指针的动作
Manager pete( "Pete", "444-55-6666", "Bakery"); Employee* ep = &pete; // Upcast Employee& er = pete; // Upcast
- 会失去关于对象的类型信息
Static Types and Dynamic Types⚓︎
- 变量自身的声明类型是变量的静态类型
- 变量引用对象的类型是变量的动态类型
- 编译器的任务是检查静态类型冲突 (static-type violation)
Polymorphic⚓︎
多态变量(polymorphic variable):
- 对象的指针或引用变量是多态变量
- 这些变量保留了对象的声明类型及其子类型
多态(polymorphism) 包括:
- 向上转型:将派生类的对象作为基类的对象
- 动态绑定:绑定被调用的函数
- 静态绑定:调用作为代码的函数
- 动态绑定:调用对象的函数
Virtual Functions⚓︎
虚函数(virtual functions)
- 非虚函数:编译器为指定类型生成静态或直接的调用——执行更快
- 虚函数:
- 在派生类中能被透明地(transparently) 重写
- 对象携带一组虚拟函数
- 编译器检查这组虚拟函数,并动态调用正确的函数
- 如果编译器在编译时知道函数,那么就会生成静态调用
虚函数和引用参数
虚析构函数
Overriding⚓︎
- 重写(overriding) 会重新定义虚函数体
- 超类和子类以相同的签名定义方法
- 每个类都可以访问自己的字段
- 超类满足静态类型检查
- 在运行时调用的子类方法会重写超类的版本
- 可以在重写的函数内调用被重写的那版函数,无需复制原来的代码
- 返回类型放宽 (relaxation)
- 假设
D
是B
的公有派生类 D::f()
返回的是在B::f()
内定义的返回类型的子类
- 假设
- 重载 (overloading) 和虚函数
- 重载需要多个函数签名
- 如果重写了一个重载函数,那么必须重写其他的重载函数,不能仅重写一个,否则的话有些函数就会被隐藏起来
提示
- 不要重新定义一个被继承的非虚函数:非虚函数是静态限制的,不可动态分派 (dispatch)
- 不要重新定义一个北极承德默认参数值:原因同上
在构造函数中的虚函数
Abstract Functions and Classes⚓︎
Multiple Inheritance⚓︎
评论区
如果大家有什么问题或想法,欢迎在下方留言~