浅谈C++|类的继承篇

 

引子: 

继承是面向对象三大特性之一、有些类与类之间存在特殊的关系,例如下图中:



我们发现,定义这些类时,下级别的成员除了拥有上一级的共性,还有自己的特性。
这个时候我们就可以考虑利用继承的技术,减少重复代码。

一.继承基本语法 

语法:class 子类:继承方式 父类 

优点:减少重复代码

子类也叫派生类,父类也叫基类

代码: 

#include <iostream>
using namespace std;
class person {   //定义person基类
public:int age;int height;int weight;string name;void show() {cout << "age=" << age << endl;cout << "height=" << height << endl;cout << "weight=" << weight << endl;cout << "name=" << name << endl;}
};class women :public person {
public:string xingbie;void shou_x() {cout << "xingbie=" << xingbie<<endl;}
};void fun() {women p;p.age = 18;p.height = 180;p.name = "tom";p.weight = 160;p.xingbie = "女";p.show();p.shou_x();
}
int main() {fun();return 0;
}

 派生类中的成员,包含两大部分:
1.类是从基类继承过来的,-类是自己增加的成员。
2.从基类继承过过来的表现其共性,而新增的成员体现了其个性。

 二.继承方式

 继承方式:

public:     公有继承

protected:保护继承

private:    私有继承

代码:

#include <iostream>
using namespace std;
class father {
public:int A;
protected:int B;
private:int C;
};class son1 :public father {    //公有继承
public:void fun() {cout << "A=" << A << endl;  //公有变为公有cout << "B=" << B << endl;  //保护变为保护//cout << "C=" << C << endl;//私有不可访问}
};class son2 :protected father {    //保护继承
public:void fun() {cout << "A=" << A << endl;  //公有变为保护cout << "B=" << B << endl;  //保护变为保护//cout << "C=" << C << endl;//私有不可访问}
};class son3 :private father {    //私有继承
public:void fun() {cout << "A=" << A << endl;  //公有变为私有cout << "B=" << B << endl;  //保护变为私有//cout << "C=" << C << endl;//私有不可访问}
};void fun() {son1 p1;son2 p2;son3 p3;p1.A = 10;p1.fun();
}
int main() {fun();return 0;
}

 私有成员全不见,公不变,保全保,私全私。

 三.继承中的对象模型

继承中,基类私有变量虽然访问不到,但是已经被继承,只是被隐藏了。

 代码:

#include <iostream>
using namespace std;
class father {
public:int A;
protected:int B;
private:int C;
};
class son :private father {
public:int age;
};
int main() {cout << sizeof(son) << endl;return 0;
}

四.继承构造和析构顺序

子类继承父类时,会先创建一个父类。析构的顺序和构造顺序正好相反。

 代码:

#include <iostream>
using namespace std;
class father {
public:father() {cout << "father的构造哈数" << endl;}~father() {cout << "father的析构函数" << endl;}
};
class son :public father {
public:son() {cout << "son的构造函数" << endl;}~son() {cout << "son的析构函数" << endl;}
};
void fun() {son a;
}
int main() {fun();return 0;
}

五.继承同名成员处理方式

当基类中的成员变量以及成员函数,和派生类的成员变量和函数重名时,基类默认调用派生类的成员函数和成员变量。要想调用基类的成员函数和成员变量,需要加上基类的作用域;

代码:

#include <iostream>
using namespace std;
class father {
public:int A;father() {A = 999;}void fun() {cout << "father的fun调用" << endl;}void fun(int a) {cout << "father的fun调用" << ' ' << a << endl;}
};
class son :public father{
public:int A;son() {A = 99;}void fun() {cout << "son的fun调用" << endl;}void fun(int a) {cout << "father的fun调用" << ' ' << a << endl;}
};
void fun() {son p;cout << "son" << ' ' << p.A << endl;cout << "father" << ' ' << p.father::A << endl;p.fun();p.fun(11);p.father::fun();p.father::fun(90);
}
int main() {fun();return 0;
}

 如果派生类中出现和基类重名的成员函数,那么派生类会隐藏基类全部重名的成员函数。需要注意的是,本来可以按照函数重载区分,却被派生类隐藏的情况:

代码: 

#include <iostream>
using namespace std;
class father {
public:int A;father() {A = 999;}void fun() {cout << "father的fun调用" << endl;}void fun(int a,int b) {cout << "father的fun调用" << ' ' << a << endl;}
};
class son :public father{
public:int A;son() {A = 99;}void fun() {cout << "son的fun调用" << endl;}
};
void fun() {son p;cout << "son" << ' ' << p.A << endl;cout << "father" << ' ' << p.father::A << endl;p.fun();p.fun();p.father::fun();//p.fun(90,89);//报错p.father::fun(89, 123);
}
int main() {fun();return 0;
}

六.继承同名static成员处理方式

 当重名的成员变量和函数是static时,需要注意通过类名来调用的方式

代码:

#include <iostream>
using namespace std;
class father {
public:static int A;static void fun() {cout << "father的fun调用" << endl;}void fun(int a) {cout << "father的fun调用" << a<<' ' << endl;}
};
int father::A=10;   //static成员变量,类内声明,类外定义
class son :public father {
public:static int A;static void fun() {cout << "son的fun调用" << endl;}
};
int son::A = 20;
void fun() {son p;//1.利用对象调用成员变量和函数cout << p.A << endl;cout << p.father::A << endl;p.fun();p.father::fun();cout << "**************************" << endl;//2.利用类名调用成员变量和函数cout << son::A << endl;cout << father::A << endl;cout << son::father::A << endl;   son::fun();father::fun();son::father::fun();    //father::fun(10);  //报错,此方法只能调用static类型}
int main() {fun();return 0;
}

七.多继承语法

C++中允许一个类继承多个类


语法: class子类∶继承方式父类1,继承方式父类2...


多继承可能会引发父类中有同名成员出现,需要加作用域区分
C++实际开发中不建议用多继承

 代码:

#include <iostream>
using namespace std;
class base1 {
public:int A;base1() {A = 10;cout << "base1构造函数调用" << endl;}
};class base2 {
public:int A;base2() {A = 20;cout << "base2构造函数调用" << endl;}
};class son :public base1, public base2 {
public:int B;int C;son() {B = 100;C = 200;cout << "son构造函数调用" << endl;}
};void fun() {son b;cout << b.base1::A << endl;cout << b.base2::A << endl;cout << b.B << endl;cout << b.C << endl;
}
int main() {fun();return 0;
}

 

 注意构造函数的调用顺序,父亲1先调用,父亲2再调用,最后son调用

总结:多继承中如果父类中出现了同名情况,子类使用时候要加作用域。

八.菱形继承

菱形继承概念:
两个派生类继承同一个基类
又有某个类同时继承者两个派生类
这种继承被称为菱形继承,或者钻石继承

1.羊继承了动物的数据,驼同样继承了动物的数据,当羊驼使用数据时,就会产生二义性。
2.羊驼将动物的数据继承了两份,其实我们应该清楚,这份数据我们只需要—份就可以。

 代码:

#include <iostream>
using namespace std;
class dongwu {
public:int A;
};
class yang :public dongwu {};
class tuo:public dongwu {};
class son :public tuo, public yang {};
void fun() {son p;p.yang::A = 100;p.tuo::A = 200;//当菱形继承,两个父亲拥有相同名的成员时,要加作用域加以区分;cout << p.yang::A << endl;cout << p.tuo::A << endl;
}
int main() {fun();return 0;
}

此时的继承情况是,这样的。 

 利用虚继承,可以解决菱形继承的问题(两份相同的数据,浪费内存)

代码:

#include <iostream>
using namespace std;
class dongwu {
public:int A;
};
//virtual虚继承,dongwu称为虚基类
class yang :virtual public dongwu {};
class tuo:virtual public dongwu {};
class son :public tuo, public yang {};
void fun() {son p;yang p1;tuo p2;p.yang::A = 100;p.tuo::A = 200;p1.A = 90;p2.A = 190;//当菱形继承,两个父亲拥有相同名的成员时,要加作用域加以区分;cout << p.yang::A << endl;cout << p.tuo::A << endl;cout << p1.A << endl;cout << p2.A << endl;}
int main() {fun();return 0;
}

 继承时只继承一份,此时son继承的是两个虚基类表的指针,虚基类表中存储的是到成员的偏移量。

总结:
·菱形继承带来的主要问题是子类继承两份相同的数据,导致资源浪费以及毫无意义·利用虚继承可以解决菱形继承问题

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/134202.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Selenium】webdriver.ChromeOptions()官方文档参数

Google官方Chrome文档&#xff0c;在此记录一下 Chrome Flags for Tooling Many tools maintain a list of runtime flags for Chrome to configure the environment. This file is an attempt to document all chrome flags that are relevant to tools, automation, benchm…

竞赛 基于机器视觉的行人口罩佩戴检测

简介 2020新冠爆发以来&#xff0c;疫情牵动着全国人民的心&#xff0c;一线医护工作者在最前线抗击疫情的同时&#xff0c;我们也可以看到很多科技行业和人工智能领域的从业者&#xff0c;也在贡献着他们的力量。近些天来&#xff0c;旷视、商汤、海康、百度都多家科技公司研…

红外检漏技术

SF6气体绝缘设备发生泄漏后会造成运行开关闭锁、 内部绝缘击穿&#xff0c; 泄漏到空气中会造成环境污染&#xff0c; 并严重危害现场人员安全。 再加之SF6气体成本高&#xff0c; 频繁补气&#xff0c; 使维护成本增加&#xff0c; 造成经济损失。 红外检漏是依据SF6气体对红外…

EasyUI combobox 实现搜索(模糊匹配)功能

很简单的一个下拉框搜索模糊匹配功能&#xff0c;在此记录&#xff1a; 1&#xff1a;页面实现&#xff1a; <select class"easyui-combobox" name"combobox" id"combobox" style"width:135px;height:25px;" headerValue"请选…

LeetCode142.环形链表-II

这道题和上一道题几乎没有任何区别啊&#xff0c;为什么还是中等难度&#xff0c;我用上一道题的解法一分钟就写出来了&#xff0c;只不过返回的不是true和false而是节点&#xff0c;以下是我的代码&#xff1a; public class Solution {public ListNode detectCycle(ListNode…

推荐一款负载均衡器,助你轻松管理多个 Socks5 代理

推荐一款负载均衡器&#xff0c;助你轻松管理多个 Socks5 代理。 推荐一个 GitHub 开源项目 mingcheng/socks5lb&#xff0c;该项目在 GitHub 有超过 400 Star&#xff0c;用一句话介绍该项目就是&#xff1a;“A simple socks5 proxy load balance and transparent proxy”&a…

1131. 绝对值表达式的最大值

1131. 绝对值表达式的最大值 原题链接&#xff1a;完成情况&#xff1a;解题思路&#xff1a;求方向一次遍历两度统计 参考代码&#xff1a;求方向一次遍历两度统计 原题链接&#xff1a; 1131. 绝对值表达式的最大值 https://leetcode.cn/problems/maximum-of-absolute-val…

【CCF】第30次csp认证——202305-1重复局面

202305-1重复局面&#xff1a; 问题描述 国际象棋每一个局面可以用大小为 88 的字符数组来表示&#xff0c;其中每一位对应棋盘上的一个格子。六种棋子王、后、车、象、马、兵分别用字母 k、q、r、b、n、p 表示&#xff0c;其中大写字母对应白方、小写字母对应黑方。棋盘上无…

iOS开发之编译OpenSSL静态库

项目审查发现OpenSSL1.0.2d有漏洞&#xff0c;所以需要升级更新OpenSSL版本&#xff0c;借此机会&#xff0c;记录一下编译OpenSSL静态库的流程。 Xcode使用的是14.2&#xff0c;OpenSSL使用的是1.0.2u、1.1.1u&#xff0c;由于是对两个不同版本进行的编译操作&#xff0c;所以…

Linux下安装和使用MySQL的详细教程

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

js中如何获取当前页面的URL参数值?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 获取当前页面的URL参数值⭐ 解析查询字符串⭐ 使用正则表达式解析参数值⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅&am…

LC142. 环形链表 II

题目大意 给你一个链表&#xff0c;要求判断是否有环&#xff0c;若有环&#xff0c;找出环的入口结点。 142. 环形链表 II 判断是否有环 判环比较简单&#xff0c;用一个一次走一个结点的快指针&#xff0c;和一个一次走一个结点的慢指针同时遍历链表&#xff0c;若两指针相…

第一颗国产 单/双端口 MIPI CSI/DSI 至 HDMI 1.4 发射器 芯片LT9611

1. 描述 LT9611 MIPI DSI/CSI 至 HDMI1.4 桥接器具有双端口 MIPI D-PHY 接收器前端配置&#xff0c;每个端口有 4 个数据通道&#xff0c;每个数据通道以 2Gbps 的速度工作&#xff0c;最大输入带宽为 16Gbps。 该桥接器提供一个 HDMI 数据输出&#xff0c;具有可选的 …

8位和32位单片机如何选择适合,以及主要区别!

单片机直接影响到项目的成功和性能&#xff0c;我们将分享如何选择适合您的应用的8位或32位单片机。 8位单片机 vs. 32位单片机&#xff1a; 一、性能和处理能力&#xff1a; 8位单片机&#xff1a; 8位单片机通常适用于相对简单的应用&#xff0c;如传感器控制、LED显示、小…

【论文笔记】Perception, Planning, Control, and Coordination for Autonomous Vehicles

单纯作为阅读笔记&#xff0c;文章内容可能有些混乱。 文章目录 1. Introduction2. Perception3. Planning3.1. Autonomous Vehicle Planning Systems3.2. Mission Planning3.3. Behavioral Planning3.4. Motion Planning3.4.1. Combinatorial Planning3.4.2. Sampling-Based P…

JavaWeb基础学习(5)

JavaWeb基础学习 一、Filter1.1 Filter介绍1.2 Filter快速入门1.3、Filter执行流程1.4、Filter使用细节1.5、Filter-案例-登陆验证 二、Listener2.1 Listener介绍2.2、ServletContextListener使用 三、AJAX3.1 AJAX介绍与概念3.2 AJAX快速入门3.3 Axios异步架构3.4 JSON-概述和…

[管理与领导-96]:IT基层管理者 - 扩展技能 - 5 - 职场丛林法则 -10- 七分做,三分讲,完整汇报工作的艺术

目录 前言&#xff1a; 一、汇报工作的重要性 1.1 汇报的重要性&#xff1a;汇报工作是工作重要的一环 1.2 向上司汇报工作状态具有重要的意义 1.2 汇报工作存在一些误解 1.3 汇报工作中的下错误做法 1.4 汇报工作与做实际工作的关系 二、工作汇报的内容与艺术 2.1 工…

Hugging Face使用Stable diffusion Diffusers Transformers Accelerate Pipelines

Diffusers A library that offers an implementation of various diffusion models, including text-to-image models. 提供不同扩散模型的实现的库&#xff0c;代码上最简洁&#xff0c;国内的问题是 huggingface 需要翻墙。 Transformers A Hugging Face library that pr…

Ubuntu安装深度学习环境相关(yolov8-python部署)

Ubuntu安装深度学习环境相关(yolov8-python部署) 本文将从如下几个方面总结相关的工作过程&#xff1a; Ubuntu系统安装(联想小新pro16) 2.显卡驱动安装3.测试深度学习模型 1. Ubunut 系统安装 之前在台式机上安装过Ubuntu&#xff0c;以为再在笔记本上安装会是小菜一碟&…

C: . 与 -> 的区别

相同点&#xff1a; 功能相同&#xff1a;访问结构体或者类的成员。优先级相同。 不同点&#xff1a; 结构体变量用 . 来访问成员&#xff1b;结构体指针用 ->来访问成员&#xff1b; #include <stdio.h> #include<string.h> //首先定义结构体类型student&a…