🍑一、继承和派生的概述
在C++中,继承是一种对象-oriented编程(面向对象编程)的概念,它允许创建一个新的类(称为派生类)从一个现有的类(称为基类)继承属性和行为。通过继承,派生类可以获得基类的成员变量、成员函数和其他特性。
继承有几种类型:公有继承、私有继承和受保护的继承。在公有继承中,基类的公有成员在派生类中仍然是公有的;在私有继承中,基类的公有成员在派生类中变为私有的;在受保护的继承中,基类的公有成员在派生类中变为受保护的。
派生类可以通过继承来扩展基类的功能,它可以添加新的成员变量和成员函数,也可以重写基类的成员函数以改变其行为。派生类还可以访问基类的非私有成员。
继承的优点:减少代码的冗余 提高代码的重用性
一图让你认识继承和派生的概念~
🍒 二、继承的语法
派生类定义格式:
注意以下两个格式都是一样的,定义以及意义都是相同的!
class 子类: 继承方式 父类名{ //子类新增的数据成员和成员函数 }; Class 派生类名 : 继承方式 基类名{ //派生类新增的数据成员和成员函数 };
继承方式分类:
public : 公有继承 (重要)
private : 私有继承
protected : 保护继承
基类个数分类:
单继承:指每个派生类只直接继承了一个基类的特征 (一个父类 派生出 一个子类)
多继承:指多个基类派生出一个派生类的继承关系,多继承的派生类直接继承了不止一个基
类的特征(多个父类 派生出 一个子类)
注意:
子类继承父类,子类拥有父类中全部成员变量和成员方法(除了构造和析构之外的成员方法),但是在子类中,继承的成员并不一定能直接访问,不同的继承方式会导致不同的访问权限。
派生类继承基类的规则 :
一图让你理解~
🍈三、继承中的构造函数和析构函数
构造和析构的顺序
class Other { public: Other() { cout << "对象成员的构造函数" << endl; } ~Other() { cout << "对象成员的析构函数" << endl; } }; class Base { public: Base() { cout << "父类的无参构造函数" << endl; } ~Base() { cout << "父类中的析构函数" << endl; } }; class Son :public Base { public: Son() { cout << "子类的无参构造" << endl; } ~Son() { cout << "子类中的析构函数" << endl; } Other ob;//对象成员 }; void test01() { Son ob1; }
运行结果如下:
一图让你理解~
🍉子类中的构造(重要)
先看以下代码:
父类
class Base { private: int a; public: Base() { cout << "父类的无参构造函数" << endl; } Base(int a) { this-> a = a; cout << "父类的有参构造函数" << endl; } ~Base() { cout << "父类中的析构函数" << endl; } };
知识点1:
子类会默认调用 父类的 无参构造
子类1:
class Son :public Base { private: int b; public: Son() { cout << "子类的无参构造" << endl; } Son(int b) { this->b = b; cout << "子类的有参构造函数int" << endl; } ~Son() { cout << "子类中的析构函数" << endl; } }; void test01() { Son ob1(10); }
运行结果:
知识点2:
子类 必须显示 使用初始化列表 调用 父类的有参构造
子类2:
class Son :public Base { private: int b; public: Son() { cout << "子类的无参构造" << endl; } Son(int b) { this-> b = b; cout << "子类的有参构造函数int" << endl; } //子类必须用 初始化列表 显示的调用父类的有参构造 //父类名称(参数) Son(int a, int b) :Base(a)//显示的调用父类的有参构造 { this-> b = b; cout << "子类的有参构造函数 int int" << endl; } ~Son() { cout << "子类中的析构函数" << endl; } }; void test01() { //子类 默认 会调用 父类的无参构造 //子类必须用 初始化列表 显示的调用父类的有参构造 //父类名称+() Son ob2(10, 20); }
运行结果:
🥝四、父类和子类的同名处理
成员变量的处理
1、当 父类和子类 成员变量同名时 在子类就近原则 选择本作用域的子类成员
2、如果在子类中 必须使用父类中的同名成员 必须加上父类的作用域。
栗子:
class Base { //父类的私有数据 一旦涉及继承 在子类中不可见 public: int num; public: Base(int num) { this-> num = num; cout << "Base有参构造int" << endl; } ~Base() { cout << "析构函数" << endl; } }; class Son :public Base { private: int num; public: Son(int num1, int num2) :Base(num1) { this-> num = num2; cout << "有参构造int int" << endl; } ~Son() { cout << "析构函数" << endl; } void showNum(void) { //如果在子类中 必须使用父类中的同名成员 必须加上父类的作用域 cout << "父类中的num = " << Base::num << endl; //当 父类和子类 成员变量同名时 在子类就近原则 选择本作用域的子类成员 cout << "子类中的num = " << num << endl; } }; void test01() { Son ob1(10, 20); ob1.showNum(); }
运行结果:
成员函数的处理
1、子类继承父类所有成员函数 和成员变量
2、一旦子类 实现了 父类的同名成员函数 将屏蔽所有父类同名成员函数
栗子:
class Base { public: void func(void) { cout << "父类中的void func" << endl; } void func(int a) { cout << "父类中的int func a = " << a << endl; } }; class Son :public Base { public: //一旦子类 实现了 父类的同名成员函数 将屏蔽所有父类同名成员函数 void func(void) { cout << "子类中voidfunc" << endl; } }; void test01() { //为啥构造和析构除外?父类的构造和析构 只有父类自己知道该怎么做(构造和析构 系统自动调用) //子类会继承父类所有成员函数(构造和析构函数除外) 和成员变量 Son ob1; ob1.func(); //ob1.func(10);//err //一旦子类 实现了 父类的同名成员函数 将屏蔽所有父类同名成员函数 //如果用户 必须要调用父类 的同名成员函数 必须加作用域 ob1.Base::func();//调用父类的void func ob1.Base::func(10);//调用父类的int func }
运行结果:
本文仅仅为对于C++中继承的基础知识,重要的还是在虚函数那一块,下一篇,我会详细的介绍虚函数!希望大家继续支持Thanks♪(・ω・)ノ