当前位置: 首页 > ds >正文

【面向对象编程——继承和派生】

引入

继承是面向对象编程的核心特性之一,允许一个类(子类或派生类)基于另一个类(父类或基类)构建,继承父类的属性和方法,同时可以扩展或修改功能(构造函数不能继承)

简言之就是子类继承父类,父类派生出子类。

格式: class 子类名 : 访问修饰符 父类名
如: class ChildClass : public ParentClass

class animal {
public:string tname;int tage;
public:animal(){}animal(string name,int age) {this->tname = name;this->tage = age;}
void printInfo() {cout << "名字叫:" << this->tname << "年龄:" << this->tage << endl;}
};class dog :public animal {
public:char sex;
public:dog(){}dog(int age, string name, char sex) {this->tage = age;this->tname = name;this->sex = sex;}
};int main() {dog d1(2, "wangcai", 'm');d1.printInfo();return 0;
}

因为dog类继承了animal类,所以在dog类里面可以直接拥有animal里面的tname和tage以及printInfo,同时又可以自己添加成员变量、成员函数。

三种继承方式

在这里插入图片描述

根据自己的理解记忆,我是按着public限制最少、优先级最低、最容易被修改,protected占中位,private优先级最高。
比如子类public继承

  • 父类中访问修饰词是public时,子类也public;
  • 父类protected时,因优先级比public高,则子类不修改(仍为protected)。
    子类protected继承
  • 父类中访问修饰词是public时,子类继承的优先级更高,改成protected;
  • 父类protected时,子类也protected。
    子类private继承
  • 父类中访问修饰词是public或protected时,子类继承的优先级更高,均需要改成private;
    所有父类private成员在子类中都不能使用。
    如图,当修改printInfo的访问修饰符为private后再引用就报错了
    在这里插入图片描述

所说的子类的不同继承方式是由上文格式部分的访问修饰符决定的。
也就是圈住的部分:
在这里插入图片描述
完整代码:

class person {
public:string tname;
protected:int tage;
private:char tsex;public:person(){}
void setName(string name) {this->tname = name;}
void setAge(int age) {this->tage = age;
}void setSex( char sex) {this->tsex = sex;
}void printInfo() {cout << "名字叫:" << this->tname << "  年龄" << this->tage << endl;}
};class student :public person {};int main() {student s1;s1.setName("aaa");s1.setAge(10);s1.setSex('g');s1.printInfo();return 0;
}

在这里插入图片描述在这里插入图片描述

tage被protected修饰,在列表中没有tage,不能直接访问
在这里插入图片描述

但能在派生类(子类)中使用,只有private既不能直接访问又不能在派生类中使用。

public:person(){}person(string name, int age, char sex) :tname(name), tage(age), tsex(sex){}/*person(string name, int age, char sex) {this->tname = name;this->tage = age;this->tsex = sex;}*/

这两种(注释掉的部分和注释的上一行)带参数的构造函数效果是一样的(下面的展示就把注释的那种方法删掉了)。
完整代码:

class person {
public:string tname;
protected:int tage;
private:char tsex;public:person(){}person(string name, int age, char sex) :tname(name), tage(age), tsex(sex){}void printInfo() {cout << "名字叫:" << this->tname << "  年龄" << this->tage << endl;}
};class student :public person {};int main() {person s1("aa", 10, 'b');s1.printInfo();return 0;
}

前面提到过父类的构造函数不能继承给子类,但子类可以引用父类的构造函数。

子类可以引用父类的构造函数
方法一:
class person {
public:string tname;
protected:int tage;
private:char tsex;public:person(){}person(string name, int age, char sex) :tname(name), tage(age), tsex(sex){}void printInfo() {cout << "名字叫:" << this->tname << "  年龄" << this->tage << endl;}
};class student :public person {
public:double score;
public:student(){}//新增变量分开写student(string name, int age, char sex, double score) :person(name, age, sex), score(score){}void showInfo() {cout << "名字:" << this->tname << "年龄:" << this->tage << endl;}
};int main() {student s1;student s2("aaa",10,'a',11.1);s2.printInfo();return 0;
}
方法二:通过using来继承基类构造函数

格式: using 基类::基类;

class person {public:person(){}person(string name, int age, char sex) :tname(name), tage(age), tsex(sex){}void printInfo() {cout << "名字叫:" << this->tname << "  年龄" << this->tage << endl;}
public:string tname;
protected:int tage;
private:char tsex;
};class student :public person {
public:using person::person;student() {}student(string name, int age, char sex, double score) :person(name, age, sex), score(score) {}void showInfo() {cout << "名字:" << this->tname << "年龄:" << this->tage << endl;}
private:double score;
};int main() {student stu("aaa",10,'a',11.1);stu.printInfo();return 0;
}

这里与上面的代码只加了一行using person::person;不能体现出using的作用,需参考下面:

class person {
public:person() {}person(string name) : tname(name) {}person(string name, int age) : tname(name), tage(age) {}person(string name, int age, char sex) : tname(name), tage(age), tsex(sex) {}person(int age) : tage(age) {}// ... 更多构造函数
};class student : public person {
public:using person::person; // 一行代码继承所有5个构造函数// 只需要处理派生类特有的情况student(string name, int age, char sex, double score) : person(name, age, sex), score(score) {}
};
构造函数调用顺序

在这里插入图片描述

using namespace std;class animal {
public:animal() {cout << "call animal " << endl;}
};class monkey :public animal {
public:monkey() {cout << "call monkey " << endl;}
};int main() {monkey m1;return 9;
}

输出结果:先调用父类,后调用子类
在这里插入图片描述

  • 子类继承父类时实例化子类,如果不知道基类构造函数就用默认构造函数,没有就会报错。
    (默认构造函数无参数,所以很多时候会留一个空白的构造函数,如:people(){ }; 再自定义有参数的构造函数。)
析构函数调用顺序

在这里插入图片描述

class animal {
public:animal() {cout << "call animal " << endl;}~animal() {cout << "call ~animal " << endl;}
};class monkey :public animal {
public:monkey() {cout << "call monkey " << endl;}~monkey() {cout << "call ~monkey " << endl;}
};int main() {monkey m1;return 0;
}

输出:
在这里插入图片描述

http://www.xdnf.cn/news/20558.html

相关文章:

  • 脚本作业解析
  • 个人成长职业发展
  • Simulink子系统、变体子系统及封装知识
  • 山西移动九联UNT413HS-海思MV320-2+8G-原机全量备份包
  • 如何训练一个简单的Transformer模型(附源码)李宏毅2025大模型-作业4
  • 高精度地图
  • 【LeetCode - 每日1题】使数组元素都变为零的最少操作次数
  • [光学原理与应用-421]:非线性光学 - 数字信号处理中的线性与非线性运算
  • 【医学影像 AI】YoloCurvSeg:仅需标注一个带噪骨架即可实现血管状曲线结构分割
  • idf--esp32的看门狗menuconfig
  • JAVA快速学习(二)
  • xftp断网后提示错误如何继续下载?
  • Python自学12 - 常用数据结构之字典
  • 基于接口的事件机制
  • python入门常用知识
  • Phthon3 学习记录-0707
  • 积分球的使用——简易版
  • 强化学习入门:从零开始实现DDQN
  • Ai8051 2.4寸320*240 ILI9341 I8080接口驱动
  • 人工智能学习:基于seq2seq模型架构实现翻译
  • 项目初始化上传git
  • Qemu-NUC980(四):SDRAM Interface Controller
  • 什么是“二合一矫平机”?——一篇技术科普
  • 主流的开源协议(MIT,Apache,GPL v2/v3)
  • Qt编程之信号与槽
  • 吴恩达机器学习(八)
  • make时设置链接器选项的2种方法
  • 【操作系统-Day 25】死锁 (Deadlock):揭秘多线程编程的“终极杀手”
  • Zoom AI 技术架构研究:联合式方法与多模态集成
  • 【LeetCode热题100道笔记】翻转二叉树