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

关于继承

概念定义

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

public继承

含义

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

对用户

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

适用场景

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

权限如图

protected继承

含义

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

对用户

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

适应场景

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

权限如图

private继承

含义

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

对用户

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

适应场景

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

权限如图

权限的改变

改变

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

问题

  1. private继承中,基类的public和protected成员在派生类中都变为了private,为什么还可以在派生类里面访问这些成员?
    1. 当一个类通过 private 继承另一个类时,基类的 public 和 protected 成员在派生类中都变为 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++中,public、protected 和 private 访问控制是由编译器来实现的
  2. 这些访问控制机制确保了类的成员在适当的访问权限下使用,防止不当的访问和修改

如何实现

  1. 语法分析:
    1. 编译器在解析类定义时,会记录每个成员的访问权限(public、protected 或 private)
  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.

发表评论

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