王清欢Randy 王清欢Randy
首页
  • 编程语言

    • C/C++ 学习笔记
    • Golang 学习笔记
  • 算法分析

    • LeetCode 刷题笔记
  • 操作系统

    • Linux 基础
    • Vim 实用技巧
    • Shell 脚本编程
    • GDB 学习笔记
  • 开发工具

    • Git 学习笔记
  • 分布式理论

    • 共识算法
    • 分布式事务
  • 数据库内核

    • PostgreSQL
    • Postgres-XL
  • hidb
  • pgproxy
  • 实用技巧
  • 学习方法
  • 资源分享
GitHub (opens new window)
首页
  • 编程语言

    • C/C++ 学习笔记
    • Golang 学习笔记
  • 算法分析

    • LeetCode 刷题笔记
  • 操作系统

    • Linux 基础
    • Vim 实用技巧
    • Shell 脚本编程
    • GDB 学习笔记
  • 开发工具

    • Git 学习笔记
  • 分布式理论

    • 共识算法
    • 分布式事务
  • 数据库内核

    • PostgreSQL
    • Postgres-XL
  • hidb
  • pgproxy
  • 实用技巧
  • 学习方法
  • 资源分享
GitHub (opens new window)
  • C语言基础

    • 数据类型
    • 指针与字符串
    • 结构类型
    • 链表
    • 程序结构
    • 文件
  • C++面向对象编程

    • C++面向对象

      • 从 C 到 C++
      • C++ 类和对象基础
      • C++ 构造函数与析构函数
      • C++ 类和对象提高
      • 运算符重载
      • C++ 继承
        • 继承和派生的概念
        • 类之间的关系
        • 公有继承的赋值兼容
      • C++ 多态
    • C++ STL

      • C++ 输入输出流
      • C++ 泛型编程
      • C++ string类
      • C++ 标准模板库 STL 概述
      • C++ 标准模板库 STL 顺序容器
      • C++ 标准模板库 STL 函数对象
      • C++ 标准模板库 STL 关联容器
      • C++ 标准模板库 STL 容器适配器
    • C++ 新特性

      • C++11 新特性
  • C&Cpp学习笔记
  • C++面向对象编程
  • C++面向对象
王清欢
2023-11-18
目录

C++ 继承

# C++ 继承

# 继承和派生的概念

继承:在定义一个新的类 B 时,如果该类与某个已有的类 A 相似,指的是 B 拥有 A 的全部特点,在属性上 A 是 B 的子集;那么就可以把 A 作为一个基类,而把 B 作为基类的一个派生类也称为子类。

派生类:派生类是通过对基类进行修改和扩充得到的。在派生类中,继承了基类的全部成员函数和成员变量,不论是 private, protected , public,但是在派生类的各成员函数中,仍旧不能直接访问基类中的 private 成员;除此之外派生类还可以扩充新的成员变量和成员函数。派生类被定义之后,可以独立使用,不依赖于基类。

派生类的写法:

class SubClassName:public BaseClassName
{ 
    // class body 
};

派生类对象的内存空间:派生类对象占用的内存空间等于基类对象占用的内存空间,再加上自身成员变量所占用的内存空间。在派生类对象中包含这基类对象,而且基类对象的存储位置位于派生类对象自身成员变量之前。

覆盖:派生类可以定义一个和基类成员同名的成员,这种机制称为覆盖。在派生类中访问由基类定义的同名成员时,要使用作用域符号 ClassName::Member ;在派生类中同名成员没有使用作用域符号 :: 的缺省情况时,访问的是派生类自身定义的成员。

派生类的构造函数:

​ 和封闭类类似,派生类的构造函数也使用参数表的形式进行初始化,详细内容请参考 C++ 类和对象提高:成员对象和封闭类 (opens new window) 。

​ 派生类的构造函数执行顺序和封闭类也类似,在创建派生类的对象时,需要先调用基类的构造函数初始化派生类从基类继承来的成员,再调用自身的构造函数初始化自身成员变量。同理,在派生类对象消亡时,派生类的析构函数总是先于基类析构函数被调用。如果派生类包含成员对象,成员对象的构造函数后于基类构造函数调用,先于派生类自身构造函数调用;析构函数反之。

class Student{
    private:
    	string name;
    	string id;
    	char gender;
    	int age;
    public:
    	Student(const string & name_, const string & id_, char gender_, int age_){
            name = name_;
            id = id_;
            gender = gender_;
            age = age_;
        }
    	~Student(){cout<<"base class destructor called"<<endl;}
    	void printInfo(){
            cout<<"name:"<<name<<endl<<"id:"<<id<<endl<<"gender:"<<gender<<endl<<"age:"<<age<<endl;
        }
    	void setInfo(const string & name_, const string & id_, char gender_, int age_){
            name = name_;
            id = id_;
            gender = gender_;
            age = age_;
        } // 基类的成员变量是 private 的,派生类无法直接访问,通过成员函数隐藏
    	string getName(){
            return name;
        }
};

class UnderStudent:public Student{
    private:
    	string department;
    public:
    	UnderStudent(const string & name_, const string & id_, char gender_, int age_, const string & department_):Student(name_, id_, gender_, age_){
            department = department_;
        } // 派生类的构造函数使用参数表进行初始化
    	~UnderStudent(){cout<<"sub class destructor called"<<endl;}
    	void qulifiedForBaoYan(){
            cout<<"QulifiedForBaoYan"<<endl;
        }
    	void printInfo(){
            Student::printInfo(); //调用基类成员函数
            cout<<"department:"<<department<<endl;
        }
    	void setInfo(const string & name_, const string & id_, char gender_, int age_, const string & department_){
            Student::setInfo(name_, id_, gender_, age_); //调用基类成员函数
            department = department_;
        }
};

# 类之间的关系

继承关系:

​ B 是 A 的派生类,那么 B 的对象也是 A 的对象,则 A 和 B 是继承关系。

​ 例如:Man 类与 Woman 类和 Human 类都是继承关系

复合关系:

​ D 的对象是 C 的对象的固有属性或组成部分,即 C 是封闭类其成员对象是 D,则 C 和 D 是复合关系。

​ 例如:Point 类和 Circle 类是复合关系,圆不是点,所以圆心 Point 作为 Circle 类的成员对象。

# 公有继承的赋值兼容

public 继承的赋值兼容规则:如果继承方式为 private 或 protected 则下述规则不成立

  • 派生类对象可以赋值给基类对象
  • 派生类对象可以初始化基类引用
  • 派生类对象的地址可以赋值给基类指针

间接基类:派生类在声明时只需要列出其直接基类,并自动沿着类的层次关系继承其他间接基类;在派生类中也继承了间接基类的所有成员。

class Base{
    public:
    	int base;
    	Base(int base_):base(base_){cout<<"base constructor called"<<endl;}
    	~Base(){cout<<"base destructor called"<<endl;}
};

class Derived:public Base{
    public:
    	Derived(int base_):Base(base_){cout<<"derived constructor called"<<endl;}
    	~Derived(){cout<<"derived destructor called"<<endl;}
};

class MoreDerived:public Derived{
    public:
    	MoreDerived(int base_):Derived(base_){cout<<"moreDerived constructor called"<<endl;} // 间接基类的初始化
    	~MoreDerived(){cout<<"moreDerived destructor called"<<endl;}
};

int main(){
    MoreDerived obj(4);
    return 0;
}
/* output:
base constructor called
derived constructor called
moreDerived constructor called
moreDerived destructor called
derived destructor called
base destructor called
*/
上次更新: 2023/11/19, 12:55:48
运算符重载
C++ 多态

← 运算符重载 C++ 多态→

Theme by Vdoing | Copyright © 2023-2024 Wang Qinghuan | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式