博客
关于我
C++ 继承 详解
阅读量:584 次
发布时间:2019-03-12

本文共 1862 字,大约阅读时间需要 6 分钟。

继承机制入门

一、什么是继承?

继承是面向对象程序设计中代码复用最重要的手段。通过继承,可以在保持基类特性的同时,扩展功能,产生新的类——派生类。这种机制使代码更加灵活且具有可复用性。

1.1 概念

继承机制允许派生类在基类的基础上增添新的属性和行为。例如,Person 是基类,Student 是派生类。通过继承,派生类可以利用基类的功能,同时定义自己的独特逻辑。

1.2 定义
  • 基类:定义了继承关系的类,被继承的类。
  • 派生类:继承基类,扩展功能的类。
1.2.1 继承关系和访问限定符

继承关系决定了派生类对基类成员的访问级别。默认情况下,class 关键字使用私有继承(private),struct 使用公有继承(public)。建议always显式声明继承方式,以避免歧义。

1.2.2 继承基类成员访问方式的变化
  • 私有成员:基类的私有成员在派生类中始终不可见。
  • 保护成员:派生类可以访问基类的保护成员,但反之则不然。
  • 公有成员:派生类可以直接访问基类的公有成员。
注意事项
  • 基类的私有成员在派生类中不可见。
  • 使用 public 继承是最常见的选择。
  • 避免使用 protectedprivate 继承,除非有特殊需求。
  • 二、基类和派生类对象赋值转换

    可赋值关系
    • 派生类对象可以赋值给基类:通过切割(拷贝基类成员)。
    • 基类对象不能赋值给派生类:如直接赋值会导致类型不匹配。
    强制转换
    • 基类指针可以通过 dynamic_cast 安全转换为派生类指针。
    • 使用 RTTI 检测对象类型后再进行转换。
    示例
    Student sobj;Person pobj = sobj; // 可以赋值Person* pp = &sobj;Person& rp = sobj;// 错误示例sobj = pobj; // 基类对象不能赋值给派生类对象

    三、继承中的作用域

    作用域特点
  • 基类和派生类具有独立的作用域。
  • 子类成员会屏蔽父类同名成员。
  • 隐藏关系只需名称相同。
  • 示例
    class Person {protected:    string _name;    int _num;};class Student : public Person {public:    void Print() {        cout << " 姓名: " << _name << endl;        cout << " 身份证号: " << _num << endl;        cout << " 学号: " << _num << endl;    }};

    四、派生类的默认成员函数

    派生类会自动生成以下默认成员函数:

  • 构造函数:调用基类构造函数初始化基类成员。
  • 拷贝构造函数:调用基类拷贝构造。
  • 赋值运算符(`operator=``):调用基类赋值。
  • 析构函数:清理派生类成员后调用基类析构。
  • 调用顺序
    • 构造函数:基类 → 派生类。
    • 析构函数:派生类 → 基类。

    五、继承与友元

    友元关系不能继承:

    • 基类友元无法访问派生类的私有或保护成员。

    六、继承与静态成员

    静态成员在继承中仅有一个:

    • 基类定义的静态成员,派生类无法继承。

    七、菱形继承

    单继承
    • 一个子类只有一个直接父类。
    多继承
    • 子类有两个或以上直接父类。
    菱形继承
    • 子类有两个或以上父类,导致数据冗余和二义性。
    虚拟继承
    • 使用 virtual 关键字解决菱形继承的二义性问题。
    • 虚基表存储偏移量,解决数据冗余。

    八、继承与组合

    继承(is-a)
    • 派生类对象是基类对象,高耦合度。
    组合(has-a)
    • 派生类包含基类对象,低耦合度。
    优先原则
    • 综合使用对象组合而非类继承,除非有特殊需求。
    示例
    class Car {protected:    string _color;    string _num;    Tire _tire;};class BMW : public Car {public:    void Drive() {        cout << "好开-操控" << endl;    }};class Benz : public Car {public:    void Drive() {        cout << "好坐-舒适" << endl;    }}class Tire {protected:    string _brand;    size_t _size;};

    通过以上内容,可以清晰地理解继承的核心概念及其实际应用。

    转载地址:http://tertz.baihongyu.com/

    你可能感兴趣的文章
    ideal 下创建springboot项目
    查看>>
    Linux操作系统的安装与使用
    查看>>
    ajax请求出现/[object%20Object]错误的解决办法
    查看>>
    01背包(小偷的概率)
    查看>>
    流体运动估计光流算法研究
    查看>>
    如何转载博客
    查看>>
    Burpsuite工具的证书安装
    查看>>
    C++ 继承 详解
    查看>>
    OSPF多区域
    查看>>
    Grafana导入 Promethus node模板
    查看>>
    MySQL的操作
    查看>>
    算术运算符
    查看>>
    MySQL学习之《查询数据》
    查看>>
    如何提高SQL查询的效率?
    查看>>
    Docker入门之-镜像(二)
    查看>>
    设置canvas图作为背景图?亲测有效
    查看>>
    搭建Docker本地 Registry
    查看>>
    数据结构——链表(3)
    查看>>
    32位机器与64位机器在编程方面的差别
    查看>>
    socket模块和粘包现象
    查看>>