• 忘掉天地
  • 仿佛也想不起自己
bingliaolongBingliaolong  2024-06-20 21:58 Aet 隐藏边栏 |   抢沙发  10 
文章评分 2 次,平均分 5.0

关于继承

概念定义

  1. 用户
    1. 把包含这个基类或派生类的第三方类或函数暂时称为用户
  2. 基类定义如图:

public继承

含义

  1. 基类的 public 成员在派生类中仍然是 public
  2. 基类的 protected 成员在派生类中仍然是 protected
  3. 基类的 private 成员在派生类中仍然是不可访问的
    1. 只能通过基类的 publicprotected 成员函数来间接访问

对用户

  1. 用户可以通过派生类对象访问基类的 public 成员

适用场景

  1. 希望继承关系是“is-a”关系,并且希望用户能够使用基类的 public 接口时使用 public 继承

权限如图

protected继承

含义

  1. 基类的 public 成员在派生类中变成 protected
  2. 基类的 protected 成员在派生类中仍然是 protected
  3. 基类的 private 成员在派生类中仍然是不可访问的
    1. 只能通过基类的 publicprotected 成员函数来间接访问

对用户

  1. 用户不能通过派生类对象访问基类的 public 成员
    1. 因为这些成员在派生类中变成了 protected 成员

适应场景

  1. 当你希望继承关系是“is-a”关系
    1. 但不希望基类的 public 接口暴露给用户
    2. 而只希望在派生类及其子类中使用基类的接口时使用 protected 继承

权限如图

private继承

含义

  1. 基类的 public 成员在派生类中变成 private
  2. 基类的 protected 成员在派生类中变成 private
  3. 基类的 private 成员在派生类中仍然是不可访问的
    1. 只能通过基类的 publicprotected 成员函数来间接访问

对用户

  1. 用户不能通过派生类对象访问基类的任何成员
    1. 因为所有基类的成员在派生类中都变成了 private 成员

适应场景

  1. 当你希望继承关系是“is-implemented-in-terms-of”关系
    1. 且不希望基类的接口暴露给用户
    2. 甚至不希望基类的接口在派生类中公开时使用 private 继承

权限如图

权限的改变

改变

  1. public 继承:
    1. 基类的 public 成员在派生类中保持 publicprotected 成员保持 protected
  2. protected 继承:
    1. 基类的 public 成员在派生类中变为 protectedprotected 成员保持 protected
  3. private 继承:
    1. 基类的 publicprotected 成员在派生类中都变为 private

问题

  1. private继承中,基类的publicprotected成员在派生类中都变为了private,为什么还可以在派生类里面访问这些成员?
    1. 当一个类通过 private 继承另一个类时,基类的 publicprotected 成员在派生类中都变为 private
      这意味着这些成员对于派生类之外的任何代码都是不可见的(即使是从派生类派的派生类也无法访问它们)
    2. 然而,这些成员对于派生类自身的成员函数来说仍然是可访问的
      这是因为继承的访问控制只影响从外部访问的权限,而不影响派生类内部的成员函数对基类成员的访问

组合和private

组合

  1. 优点
    1. 清晰的语义:组合表达了“has-a”关系。例如,汽车有一个发动机 (Car has an Engine)
    2. 更灵活:组合允许在运行时动态替换组件或成员对象。例如,可以在运行时替换汽车的发动机
    3. 低耦合度:组合使得类之间的耦合度较低,更容易维护和扩展
    4. 清晰的接口:组合可以清晰地定义类之间的接口,避免不必要的成员暴露
  2. 缺点
    1. 可能需要更多的代码:需要在成员对象上显式调用方法,增加了代码复杂性
    2. 不能直接访问成员类的保护成员:需要成员类提供合适的接口
  3. 示例:

private

  1. 优点
    1. 简化代码:派生类可以直接访问基类的成员,而不需要额外的代码包装。
    2. 表达实现细节private 继承表达了“is-implemented-in-terms-of”的关系,可以将基类的实现细节封装在派生类中
  2. 缺点
    1. 强耦合private 继承导致派生类和基类之间的耦合度较高,如果基类发生变化,派生类也需要相应修改
    2. 不清晰的接口:基类的实现细节暴露在派生类中,可能导致接口不清晰
    3. 继承层次复杂:使用多重继承时,private 继承可能导致继承层次复杂化,增加代码的维护难度
  3. 示例:

权限总结

  1. 不管是什么样的继承方式:

    1. 派生类可以访问基类的 public 成员和函数
    2. 派生类可以访问基类的 protected 成员和函数
    3. 派生类不能直接访问基类的 private 成员和函数
  2. 对于用户:

    1. 只有在public继承的情况下,用户可以通过派生类访问基类的public成员

关于实现原理

概述

  1. C++中,publicprotectedprivate 访问控制是由编译器来实现的
  2. 这些访问控制机制确保了类的成员在适当的访问权限下使用,防止不当的访问和修改

如何实现

  1. 语法分析
    1. 编译器在解析类定义时,会记录每个成员的访问权限(publicprotectedprivate
  2. 语义检查
    1. 在编译过程中,编译器会检查对类成员的每一次访问,根据记录的访问权限进行验证
    2. 如果发现访问权限违规,编译器会生成编译错误
  3. 代码生成
    1. 在生成目标代码时,编译器确保只有合法的访问会被转换成机器指令,非法访问会在编译阶段被阻止

MSVC

  1. 符号表和访问控制
    1. MSVC 在编译期间维护一个符号表,用于存储类的成员信息,包括其类型、名称和访问权限
    2. 在语法分析阶段,编译器会将每个类成员的访问权限信息记录在符号表中
  2. 访问控制检查
    1. 在语义分析阶段,MSVC 会检查每个成员的访问
      如果一个成员的访问权限不匹配当前的访问上下文,编译器会生成一个错误
    2. MSVC 使用特定的错误代码和消息来报告访问权限违规
      例如 C2248 错误(尝试访问私有成员)
  3. 代码生成
    1. 在通过访问控制检查后,MSVC 会继续进行代码生成
    2. 合法的成员访问会被转换为相应的机器指令,不合法的访问会在编译阶段被阻止,因此不会出现在生成的目标代码中

本文为原创文章,版权归所有,欢迎分享本文,转载请保留出处!

bingliaolong
Bingliaolong 关注:0    粉丝:0 最后编辑于:2024-07-02
Everything will be better.

发表评论

表情 格式 链接 私密 签到
扫一扫二维码分享