第一百零四天学习记录:C++核心:类和对象Ⅶ(五星重要)继承下

news/2024/4/28 4:35:21/文章来源:https://blog.csdn.net/weixin_45694614/article/details/131629745

继承同名成员处理方式

1、访问子类同名成员,直接访问即可
2、访问父类同名成员,需要加作用域

#include<iostream>
using namespace std;
class Base
{
public:Base(){m_A = 100;}int m_A;void func(){cout << "Base - func()调用" << endl;}void func(int a){cout << "Base - func(int a)调用" << endl;}
};class Son :public Base
{
public:Son(){m_A = 200;}int m_A;void func(){cout << "Son - func()调用" << endl;}
};//同名成员属性处理
void test01()
{Son s;cout << "Son 下 m_A = " << s.m_A << endl;//如果通过子类对象 访问到父类中同名成员,需要加作用域cout << "Base 下 m_A = " << s.Base::m_A << endl;
}//同名成员函数处理
void test02()
{Son s;s.func();s.Base::func();//s.func(100);//报错//如果子类种出现和父类同名的成员函数,子类的同名成员会隐藏掉父类中所有的同名成员函数。//如果想访问到父类中被隐藏的同名成员函数,需要加作用域s.Base::func(100);
}int main()
{test01();test02();return 0;
}

总结:
1、子类对象可以直接访问到子类中同名成员
2、子类对象加作用域可以访问到父类同名成员
3、当子类与父类拥有同名的成员函数,子类会隐藏父类中同名成员函数,加作用域可以访问到父类中同名函数。

继承同名静态成员处理方式

静态成员和非静态成员出现同名,处理方式一致
1、访问子类同名成员 直接访问即可
2、访问父类同名成员 需要加作用域

#include<iostream>
using namespace std;//继承中的同名静态成员处理方式
class Base
{
public:static int m_A;static void func(){cout << "Base - static void func()" << endl;}static void func(int a){cout << "Base - static void func(int a)" << endl;}
};
int Base::m_A = 100;class Son :public Base
{
public:static int m_A;static void func(){cout << "Son - static void func()" << endl;}
};
int Son::m_A = 200;//同名静态成员属性
void test01()
{//1、通过对象访问cout << "通过对象访问:" << endl;Son s;cout << "Son 下 m_A = " << s.m_A << endl;cout << "Base 下 m_A = " << s.Base::m_A << endl;//2、通过类名访问cout << "通过类名访问:" << endl;cout << "Son 下 m_A = " << Son::m_A << endl;//第一个::代表通过类名方式访问 第二个::代表访问父类作用域下cout << "Base 下 m_A = " << Son::Base::m_A << endl;
}//同名静态成员函数
void test02()
{//1、通过对象访问cout << "通过对象访问:" << endl;Son s;s.func();s.Base::func();//2、通过类名访问cout << "通过类名访问:" << endl;Son::func();Son::Base::func();//子类出现和父类同名静态成员函数,也会隐藏父类中所有同名成员函数//如果想访问父类中被隐藏同名成员,需要加作用域Son::Base::func(100);
}int main()
{test01();test02();return 0;
}

在这里插入图片描述

多继承语法

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

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

多继承可能会引发父类中有同名成员出现,需要加作用域区分

C++实际开发中不建议用多继承

#include<iostream>
using namespace std;class Base1
{
public:Base1(){m_A = 100;}int m_A;
};class Base2
{
public:Base2(){m_A = 200;}int m_A;
};//子类  需要继承Base1和Base2
//语法:class 子类: 继承方式 父类1,继承方式 父类2……
class Son :public Base1, public Base2
{
public:Son(){m_C = 300;m_D = 400;}int m_C;int m_D;
};void test01()
{Son s;cout << "sizeof Son = " << sizeof(s) << endl;//当父类中出现同名成员,需要加作用域区分cout << "Base1::m_A = " << s.Base1::m_A << endl;cout << "Base2::m_A = " << s.Base2::m_A << endl;
}int main()
{test01();return 0;
}

菱形继承

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

举例:
在这里插入图片描述
截图转自黑马程序员免费教学视频

菱形继承问题:
1、羊继承了动物的数据,驼同样继承了动物的数据,当羊驼使用数据时,就会产生二义性。
2、羊驼继承自动物的数据继承了两份,其实我们应该清楚,这份数据我们只需要一份就可以。

#include<iostream>
using namespace std;//动物类
class Animal 
{
public:int m_Age;
};//羊类
class Sheep:public Animal{};//驼类
class Tuo :public Animal {};//羊驼类
class SheepTuo :public Sheep, public Tuo {};void test01()
{SheepTuo st;//st.m_Age = 18;//报错st.Sheep::m_Age = 18;st.Tuo::m_Age = 28;//当菱形继承时,两个父类拥有相同数据,需要加以作用域区分cout << "st.Sheep::m_Age = " << st.Sheep::m_Age << endl;cout << "st.Tuo::m_Age = " << st.Tuo::m_Age << endl;//这份数据我们知道 只有一份就可以,菱形继承导致数据有两份,造成资源浪费
}int main()
{test01();return 0;
}

在这里插入图片描述
利用虚继承可以解决菱形继承的问题:
在这里插入图片描述

vbptr 虚基类指针
v - virtual
b - base
ptr - pointer
vbptr 指向 vbtable 虚基类表
在这里插入图片描述
总结:
1、菱形继承带来的主要问题是子类继承两份相同的数据,导致资源浪费以及毫无意义
2、利用虚继承可以解决菱形继承问题

问:虚基类表和虚函数表有什么关系?
答:
虚基类表(Virtual Base Table)和虚函数表(Virtual Function Table,也称为虚函数指针表)是C++中实现多态性的机制中的两个重要概念,它们有一定的关联。

虚基类表是用来处理菱形继承中的虚基类的,它记录了派生类对象中虚基类的偏移量信息。当派生类中含有虚基类时,派生类对象会包含一个指向虚基类表的指针(vbptr),通过该指针可以访问到派生类对象中虚基类的偏移量信息。虚基类表的作用是保证派生类对象中只有一份虚基类子对象,从而避免数据冗余和二义性的问题。

虚函数表是用来实现动态多态性的机制,它存储了虚函数的地址。每个含有虚函数的类都会创建一个对应的虚函数表。当一个类对象被创建时,会在对象的内存布局中添加一个指向该类的虚函数表的指针(vptr)。通过这个指针,可以在运行时动态地调用对象的虚函数,实现多态性。

虚基类表和虚函数表是两个独立的概念,但它们都涉及到在对象内存中存储额外的指针。虚基类表用于处理虚基类的偏移量,在派生类对象中只有一份虚基类的实例。虚函数表用于实现动态多态性,通过虚函数表的指针可以在运行时根据对象的实际类型来调用对应的虚函数。它们都是C++语言中实现多态性的重要机制。

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

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

相关文章

C++图形开发(16):绘制一个圆环和一根针

文章目录 绘制一个圆环和一根针1.1 绘制1.2 line()函数1.3 circle()函数1.4 setlinestyle()函数1.5 setlinecolor()函数 接下来&#xff0c;我会继续制作一些小游戏&#xff0c;但因为整个难度的上升&#xff08;毕竟我也是初学者&#xff09;&#xff0c;可能文章不会再像之前…

spring复习:(22)实现了BeanNameAware等Aware接口的bean,相应的回调方法是在哪里被调用的?

AbstractAutowireCapableBeanFactory的doCreateBean用来创建bean, 其中调用了initializeBean方法对bean进行初始化 initializeBean包含如下代码&#xff1a; 而invokeAwareMethods代码如下&#xff1a; 可见其分别判断是否实现了BeanNameAware接口、BeanClassLoaderAware接口…

如何利用PLC远程通讯模块搭建PLC远程控制系统

随着工业自动化的快速发展&#xff0c;PLC&#xff08;可编程逻辑控制器&#xff09;作为重要的控制设备&#xff0c;被广泛应用于工厂和生产线的自动化控制系统。然而&#xff0c;传统的PLC控制系统受限于物理连接和局域网范围内的限制&#xff0c;无法实现远程监控和控制&…

dp算法 力扣174地下城游戏

在学习编程时&#xff0c;算法是一道硬菜&#xff0c;而dp作为算法的一份子&#xff0c;它的地位在编程界举足轻重。 174. 地下城游戏 - 力扣&#xff08;LeetCode&#xff09; 本文是Java代码哦~ 一、题目详情 恶魔们抓住了公主并将她关在了地下城 dungeon 的 右下角 。地…

React中 Real DOM 和 Virtual DOM 的区别?优缺点?

一、是什么 Real DOM&#xff0c;真实 DOM&#xff0c;意思为文档对象模型&#xff0c;是一个结构化文本的抽象&#xff0c;在页面渲染出的每一个结点都是一个真实 DOM 结构&#xff0c;如下&#xff1a; Virtual Dom&#xff0c;本质上是以 JavaScript 对象形式存在的对 DOM …

代码随想录算法学习心得 44 | 309.最佳买卖股票的时机含冷冻期、714.买卖股票的最佳时机含手续费、最近买卖股票时机总结...

一、最佳买卖股票的时机含冷冻期 链接&#xff1a;力扣 描述&#xff1a;给定一个整数数组prices&#xff0c;其中第 prices[i] 表示第 i 天的股票价格 。​ 设计一个算法计算出最大利润。在满足以下约束条件下&#xff0c;你可以尽可能地完成更多的交易&#xff08;多次买…

k8s 大量 pod 处于 ContainerStatusUnknown 状态

如图所示&#xff0c;nexus 正常运行&#xff0c;但产生了大量的状态不明的 pod&#xff0c;原因也无从所知 解决办法&#xff0c;删除多余的 pod&#xff0c;一个一个删除&#xff0c;非常费劲 获取 namespace 中状态为 ContainerStatusUnknown 的 pod&#xff0c;并删除 …

什么是深度学习的误差分解

误差分解是将深度学习模型的预测误差拆分为多个组成部分&#xff0c;以便更好地理解模型性能。在深度学习中&#xff0c;我们通常将预测误差分解为三个部分&#xff1a;偏差&#xff08;Bias&#xff09;、方差&#xff08;Variance&#xff09;和不可避免的误差&#xff08;Ir…

2. CSS3的新特性

2.1CSS3的现状 ●新增的CSS3特性有兼容性问题, ie9才支持 ●移动端支持优于PC端 ●不断改进中 ●应用相对广泛 ●现阶段主要学习: 新增选择器和盒子模型以及其他特性 CSS3给我们新增了选择器,可以更加便捷,更加自由的选择目标元素&#xff1a; 1.属性选择器 2.结构伪类选择器…

【UE】运行游戏时就获取鼠标控制

问题描述 我们经常在点击运行游戏后运行再在视口界面点击一下才能让游戏获取鼠标控制。其实只需做一个设置就可以在游戏运行后自动获取鼠标控制。 解决步骤 点击编辑器偏好设置 如下图&#xff0c;点击“播放”&#xff0c;再勾选“游戏获取鼠标控制” 这样当你运行游戏后直…

熬夜敲代码不伤眼,选好灯具很重要

文章目录 一、引言1.1 程序员的痛点&#xff1a;长时间使用电脑对眼睛的损害1.2 保护眼睛的重要性 二、明基ScreenBar Halo的保护眼睛功能2.1 自动调光&#xff1a;根据环境光调整亮度2.2 非对称光学设计&#xff1a;减少反光和刺眼2.3 沉浸式灯光&#xff1a;照亮全场视野&…

使用Pycharm

本人没有单独安装python&#xff0c;而是直接安装了anaconda 使用Pycharm创建项目 项目取名为HelloWorld&#xff0c;环境使用前面安装的anaconda pycharm安装模块的方法&#xff1a; 打开Pycharm>File > Settings>Project: Python>Project Interpreter

计网笔记--运输层(vital)

1--运输层概述 运输层的任务&#xff1a; 为运行在不同主机上的应用进程提供直接的通信服务&#xff1b; 运输层为应用层提供了两种不同的运输协议&#xff1a; 面向连接的 TCP 和无连接的 UDP 协议&#xff1b; 2--端口号、复用与分用的概念 端口号&#xff1a; 端口号用于区分…

Kotlin基础(五):类和接口

前言 本文主要讲解类和接口&#xff0c;主要包括类的声明、构造器、类成员、修饰符、类的继承、接口、抽象类。 Kotlin文章列表 Kotlin文章列表: 点击此处跳转查看 目录 1.1 类的声明 在 Kotlin 中&#xff0c;类的声明使用关键字 class。下面是一个简单的类声明的示例&…

感受C++模版的所带来的魅力

一、泛型编程思想 首先我们来看一下下面这三个函数&#xff0c;如果学习过了 C函数重载 和 C引用 的话&#xff0c;就可以知道下面这三个函数是可以共存的&#xff0c;而且传值会很方便 void Swap(int& left, int& right) {int temp left;left right;right temp; }…

springboot项目target下面没有mapper.xml文件

文件结构是这个样子,mapper.xml文件在resources/mappers/fdms目录下面 通常来说, 将mapper打包到target目录下只需要在maven下面配置 <resources><resource><directory>src/main/resources</directory><filtering>true</filtering><inc…

【实战项目】c++实现基于reactor的高并发服务器

基于Reactor的高并发服务器&#xff0c;分为反应堆模型&#xff0c;多线程&#xff0c;I/O模型&#xff0c;服务器&#xff0c;Http请求和响应五部分 全局 反应堆模型 Channel 描述了文件描述符以及读写事件&#xff0c;以及对应的读写销毁回调函数&#xff0c;对应存储arg读…

ARM架构介绍

概览 Arm 架构为处理器或内核&#xff08;称为处理单元PE&#xff09;的设计提供了基础。 Arm架构已经集成到许多片上系统 (SoC) 设备中&#xff0c;比如智能手机、微型计算机、嵌入式设备、服务器甚至超级计算机。 Arm架构为软件开发人员提供了通用指令集和工作流程&#x…

爬取 2 万多张 Flickr 图片,莫纳什大学复现 10 年间日本樱花开放的时空特征

内容一览&#xff1a;近年来&#xff0c;全球气候变化形势严峻&#xff0c;由此引发的蝴蝶效应&#xff0c;正深刻地影响着人类和大自然。在这一背景下&#xff0c;收集数百甚至数千公里范围内开花模式的数据&#xff0c;了解气候变化如何对开花植物产生影响&#xff0c;成为近…

python -m 是什么命令

python -m 命令是什么意思 首先python --help 可以看到-m的含义&#xff1a;意思是将库中的python模块用作脚本去运行。 python --help 命令显示结果 python -m xxx.py 和python xxx.py 有什么区别 这是两种加载py文件的方式: 叫做直接运行&#xff08;python xxx.py&#xf…