当前位置: 首页 > 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/20451.html

相关文章:

  • 【Flask】测试平台开发,重构提测管理页面-第二十篇
  • 把装配想象成移动物体的问题
  • java基础学习(五):对象中的封装、继承和多态
  • C++经典的数据结构与算法之经典算法思想:排序算法
  • phpMyAdmin文件包含漏洞复现:原理详解+环境搭建+渗透实战(windows CVE-2014-8959)
  • 吴恩达机器学习(七)
  • 综合安防集成系统解决方案,智慧园区,智慧小区安防方案(300页Word方案)
  • 《2025国赛/高教杯》C题 完整实战教程(代码+公式详解)
  • 关于连接池
  • 【PostgreSQL】如何实现主从复制?
  • 网络原理-
  • 在Ubuntu平台搭建RTMP直播服务器使用SRS简要指南
  • Qt 基础教程合集(完)
  • 分布式数据架构
  • 硬件开发_基于物联网的老人跌倒监测报警系统
  • 数据结构——栈(Java)
  • MySQL数据库约束和设计
  • 附050.Kubernetes Karmada Helm部署联邦及使用
  • C++_哈希
  • 基于阿里云ECS搭建Tailscale DERP中继服务器:提升跨网络连接速度
  • 前端登录鉴权详解
  • C++面试10——构造函数、拷贝构造函数和赋值运算符
  • 西门子S7-200 SMART PLC:编写最基础的“起保停”程序
  • [特殊字符] 从零到一:打造你的VSCode圈复杂度分析插件
  • Linux内核源码获取与编译安装完整指南
  • Java8函数式编程之Stream API
  • 预闪为什么可以用来防红眼?
  • C/C++动态爱心
  • Caffeine Weigher
  • 蓓韵安禧DHA纯植物藻油纯净安全零添加守护母婴健康