跳转至

Polymorphism⚓︎

739 个字 3 行代码 预计阅读时间 4 分钟

Subclasses and Subtyping⚓︎

  • 类定义类型
  • 子类定义子类型 (subtypes)
  • 子类的对象可以用在子类型的对象需要的地方(这称为代换 (substitution)
  • 子类对象可被赋予子类指针变量
  • 子类对象可作为超类的参数
  • 公有继承里面包含了代换

    • 如果 B xxx A,那么使用 A 的同时也在使用 B,且对于 A 而言是 true 的东西对于 B 而言也是 true
    • 当心不合法的代换
  • 对于 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)
    • 假设 DB 的公有派生类
    • D::f() 返回的是在 B::f() 内定义的返回类型的子类
  • 重载 (overloading) 和虚函数
    • 重载需要多个函数签名
    • 如果重写了一个重载函数,那么必须重写其他的重载函数,不能仅重写一个,否则的话有些函数就会被隐藏起来

提示

  • 不要重新定义一个被继承的非虚函数:非虚函数是静态限制的,不可动态分派 (dispatch)
  • 不要重新定义一个北极承德默认参数值:原因同上

在构造函数中的虚函数

Abstract Functions and Classes⚓︎

Multiple Inheritance⚓︎

评论区

如果大家有什么问题或想法,欢迎在下方留言~