C++基础——继承(下)

一、继承与静态成员

基类定义了static 静态成员,则整个继承体系里面只有一个这样的成员。无论派生出多少个子

类,都只有一个 static 成员实例 。


class person
{
public:
	person(const char* name = "lisi")
	:_name(name)
	{}
public:
	string _name;
    // 静态成员属性
	static int count;
};
class worker : public person
{
public:
 
protected:
	string _job_number = "111";
};
// 静态成员属性需要在类外定义
int person::count = 0;
 
void Test2(void)
{
	person pobj;
	worker wobj;
 
    pobj._name = "wangwu";
	cout << pobj._name << endl;
	cout << wobj._name << endl;
 
	cout << "wobj.count: " << wobj.count << endl;
	// 基类更改这个静态成员
	pobj.count = 5;
	cout << "wobj.count: " << wobj.count << endl;
 
	cout << "&pobj.count = " << &pobj.count << endl;
	cout << "&wobj.count = " << &wobj.count << endl;
}

静态成员属性需要在类外定义;

上面的_name,基类对象和派生类对象各自私有一份,而对于静态成员变量 count,派生类继承的 count 和基类里面的 count 是同一份。

即基类里面的静态成员,无论有多少个派生类,它们都共享同一个静态成员。

二、单继承

单继承:一个派生类只有一个直接基类,我们称这个继承关系为单继承。

class Person{};
class Worker : public Person{};
class Teacher : public Worker{};

三、多继承

多继承:一个派生类有两个或以上直接基类时称这个继承关系为多继承。

四、菱形继承

类似以上继承为菱形继承。

菱形继承会产生数据冗余和二义性的问题。在Assistant的对象中Person成员会有两份。

二义性无法明确知道访问的是哪一个,需要显示指定访问哪个父类的成员可以解决二义性问题,但是数据冗余问题无法解决。

那么该怎么解决呢?

虚拟继承可以解决菱形继承的二义性和数据冗余的问题。

五、虚拟继承

为解决菱形继承的二义性和数据冗余,我们采用菱形继承,我们看以下代码:

class A
{
public:
	int _a;
};
// class B : public A
class B : virtual public A
{
public:
	int _b;
};
// class C : public A
class C : virtual public A
{
public:
	int _c;
};
class D : public B, public C
{
public:
	int _d;
};
int main()
{
	D d;
	d.B::_a = 1;
	d.C::_a = 2;
	d._b = 3;
	d._c = 4;
	d._d = 5;
	return 0;
}

六、总结

1.很多人说C++语法复杂,其实多继承就是一个体现。有了多继承,就存在菱形继承,有了菱形继承就有菱形虚拟继承,底层实现就很复杂。所以一般不建议设计出多继承,一定不要设计出菱形继承。否则在复杂度及性能上都有问题。

2.多继承可以认为是C++的缺陷之一,很多后来的语言都没有多继承,如Java

3.继承和组合的区别?什么时候用继承?什么时候用组合?


继承和组合是面向对象编程中两种常见的代码重用机制,它们有不同的使用场景和特点。

继承:

  • 继承是一种“is-a”关系,它描述了两个类之间的一种层次结构,子类继承了父类的属性和方法,并且可以添加自己的新属性和方法。
  • 适合于在现有类的基础上进行扩展,通过重用现有类的代码来实现新类的功能。
  • 通常用于描述一种分类或分类的关系,子类是父类的特例,具有更具体的特征或行为。
  • 适用于需要实现代码的重用和扩展的情况。

组合:

  • 组合是一种“has-a”关系,它描述了两个类之间的一种包含关系,一个类包含另一个类的实例作为其成员变量。
  • 适合于描述一种包含关系,其中一个类包含另一个类的实例,并且通过这种组合来实现更复杂的功能。
  • 通常用于描述一种组合或拥有关系,其中一个类包含了另一个类的实例作为其一部分。
  • 适用于需要将不同的类组合在一起实现某个功能的情况,而不是通过继承来实现。

在未来代码设计中,遵循的设计原则是:低耦合,高内聚。

在选择继承还是组合时,可以考虑以下几点:

  • 代码重用性:如果需要重用现有类的代码并扩展其功能,则可以选择继承。如果只是需要利用现有类的功能而不需要扩展其功能,则可以选择组合。
  • 耦合性:继承会增加类之间的耦合性,子类与父类之间存在较强的依赖关系,而组合可以降低耦合性,类之间的关系更灵活。
  • 设计灵活性:组合比继承更灵活,因为可以随时更改组合关系,而不会影响类的结构。继承则更加静态,子类的结构受限于父类的定义。

4.如何定义一个无法被继承的类?

第一种方式C++98,将基类的构造私有化,派生类继承这个基类,在实例化对象时,需要调用基类的构造,但由于基类的构造已经私有化,故会编译报错。

class A
{
public:
    
//将基类的构造函数私有化
private:   
	A(int a = int())
	:_a(a)
	{
		cout << "A()" << endl;
	};
protected:
	int _a;
};
 
class B : public A
{
protected:
	int _b;
};

对于 C++11 的做法是:通过关键字 final,被final修饰的类无法被继承,编译器会强制检查。

// 用 final 修饰 A类, 此时A类无法被继承
class A final
{
public:
	A(int a = int()) 
	:_a(a)
	{
	    cout << "A()" << endl;
	}
protected:
	int _a;
};
 
class B : public A
{
protected:
	int _b;
};

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

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

相关文章

Trieve实践:好用功的开源RAG

目录 RAG概述 RAG架构 Trieve Trieve介绍 Trieve使用 初始化 自行搭建RAG Trieve是什么&#xff0c;RAG是什么&#xff0c;本文来带你了解。其实在很多产品应用里面都会有RAG,比如ai客服&#xff0c;针对性的智能问答&#xff0c;都是基于RAG实现的 RAG概述 RAG 是一种…

Electron学习笔记(五)

文章目录 相关笔记笔记说明 七、系统1、系统对话框2、自定义窗口菜单3、系统右键菜单4、快捷键(1)、监听网页按键事件 &#xff08;窗口需处于激活状态&#xff09;(2)、监听全局按键事件 &#xff08;窗口无需处于激活状态&#xff09;(3)、补充&#xff1a;自定义窗口菜单快捷…

力扣刷题 day2

快乐数 202. 快乐数 - 力扣&#xff08;LeetCode&#xff09;   图: java // 快乐数 --> 19 > 1^2 9 ^2 82 > 82 > 8 ^ 2 2 ^ 2 ......public boolean isHappy(int n) {// 使用快慢指针int slow n, fast getSum(n);while (slow ! fast) {slow getSum(slo…

十大排序算法之->归并排序

一、归并排序简介 归并排序是一种基于分治策略的有效且稳定的排序算法。归并排序由约翰冯诺伊曼提出&#xff0c;是计算机科学中一个非常基础且历史悠久的算法。 归并排序利用分治法的策略&#xff0c;将一个大的数组拆分成几个小的子数组&#xff0c;这些子数组各自独立地排…

2024中国应急(消防)品牌巡展西安站成功召开!惊喜不断

消防品牌巡展西安站 5月10日&#xff0c;由中国安全产业协会指导&#xff0c;中国安全产业协会应急创新分会、应急救援产业网联合主办&#xff0c;陕西消防协会协办的“一切为了安全”2024年中国应急(消防)品牌巡展-西安站成功举办。该巡展旨在展示中国应急&#xff08;消防&am…

免费体验GPT-4o这5大功能,非常好用!

这几天&#xff0c;OpenAI发布了新的GPT版本&#xff0c;GPT-4o&#xff0c;比GPT4更加智能也更快。 据说&#xff0c;GPT-4o在文本、推理和编码智能方面实现了GPT-4 Turbo级别的性能&#xff0c;在多语言、文本、音频和视觉功能方面甚至超过了市面上所有同类产品。 有几个亮点…

树链剖分详解,看这一篇就够了

前置知识&#xff1a; 树形结构链式前向星(熟练)线段树(熟练)DFS序(熟练)LCA(了解定义) 什么是树链剖分 树链剖分其实有两种&#xff1a;重链剖分和长链剖分。重链剖分就是把儿子节点最重的儿子称为重儿子&#xff0c;把树分成若干条重链&#xff08;如图一&#xff09;&#…

雍禾植发张东宏:以诚相待毛发患者

医学道路上的奋斗往往需要坚定的信念和不懈的努力。对于张东宏医生来说&#xff0c;医学并非止步于书本知识&#xff0c;而是一次次与患者对话、一次次实操中的历练和积累。在他的成长历程中&#xff0c;医学之路如同一棵参天大树&#xff0c;每一步都是扎实的打磨&#xff0c;…

2024年CSPM考试时间线梳理!

最近后台有朋友在问今年CSPM的考试安排&#xff0c;给大家整理一下&#xff0c;需要的朋友认真查看&#xff0c;不要错过考试。2024年5月12日举行了本年度第二次CSPM3级考试~接下来的考试安排如下&#xff1a; 1&#xff09;2024年CSPM考试安排 本次考试出成绩时间——2024年6…

【RSGIS数据资源】2001-2021 年亚洲季风区主要国家作物种植制度数据集

文章目录 1. 数据集概况2. 数据格式3. 文件名命名规则4. 数据生产服务单位5. 元数据6. 数据引用与参考文献引用 1. 数据集概况 2001-2021 年亚洲季风区主要国家作物种植制度数据集&#xff08;ACIA500&#xff09;是结合MODIS 影像和现有的土地利用等多源数据&#xff0c;基于…

QT状态机1-三态循环状态机

#include "MainWindow.h" #include "ui_MainWindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)

【半夜学习MySQL】复合查询(含多表查询、自连接、单行/多行子查询、多列子查询、合并查询等详解)

&#x1f3e0;关于专栏&#xff1a;半夜学习MySQL专栏用于记录MySQL数据相关内容。 &#x1f3af;每天努力一点点&#xff0c;技术变化看得见 文章目录 回顾基本查询多表查询自连接子查询单行子查询多行子查询多列子查询在from子句中使用子查询合并查询 回顾基本查询 下面使用…

使用python给图片加上文字水印

使用python给图片加上文字水印 作用效果代码 作用 给图片加上文字水印文字水印的字体&#xff0c;颜色&#xff0c;位置可自定义 效果 原图&#xff1a; 加水印后的图&#xff1a; 代码 from PIL import Image, ImageDraw, ImageFontdef add_text_watermark(input_image…

Linux 无名信号量(Semaphore)的使用

目录 一、无名信号量的概念二、无名信号量相关函数三、信号量的使用步骤四、应用场景五、测试代码 一、无名信号量的概念 Linux无名信号量&#xff08;Semaphore&#xff09;   在Linux操作系统中&#xff0c;信号量&#xff08;Semaphore&#xff09;是一种用于进程间或线程…

OSG编程指南<二十三>:基于OSG+ImGui制作模型编辑器,实现三轴方向的实时平移、旋转和缩放变化

1、概述 在OSG的开发应用过程中&#xff0c;我们有时候总会纠结于使用MFC还是Qt来嵌入OSG窗口以便于后续的功能开发&#xff0c;毕竟选择一个合适的UI框架&#xff0c;对于后续的开发还是省去很多麻烦的。但对于初学者来说&#xff0c;可能对框架消息机制的不熟悉&#xff0c;尤…

景源畅信电商:做抖音有哪些未开发的蓝海领域?

在互联网信息爆炸的今天&#xff0c;抖音已经成为人们获取信息和娱乐的重要渠道。然而&#xff0c;随着用户数量的增加和内容的丰富&#xff0c;抖音的红海竞争也日益激烈。在这样的背景下&#xff0c;寻找还未被充分开发的蓝海领域&#xff0c;对于内容创作者来说&#xff0c;…

基于微信小程序+JAVA Springboot 实现的【智慧乡村旅游服务平台】app+后台管理系统 (内附设计LW + PPT+ 源码+ 演示视频 下载)

项目名称 项目名称&#xff1a; 基于微信小程序的智慧乡村旅游服务平台的设计与实现 项目技术栈 该项目采用了以下核心技术栈&#xff1a; 后端框架/库&#xff1a; Java SSM框架数据库&#xff1a; MySQL前端技术&#xff1a; 微信开发者工具、uni-app其他技术&#xff1a…

Darknet+ros+realsenseD435i+yolo(ubuntu20.04)

一、下载Darknet_ros mkidr -p yolo_ws/src cd yolo_ws/src git clone --recursive https://github.com/leggedrobotics/darknet_ros.git #因为这样克隆的darknet文件夹是空的&#xff0c;将darknet_ros中的darknet的文件替换成如下 cd darknet_ros git clone https://github.…

自定义注解

例如写一个注解PrintTime 如下&#xff1a; import java.lang.annotation.*;//下面的注解属于元注解 Target({ElementType.PARAMETER,ElementType.METHOD}) Retention(RetentionPolicy.RUNTIME) Inherited Documented public interface PrintTime {/*** 注解的属性*/public S…

JavaScript 进阶(二)

一、深入对象 1. 创建对象的三种方式 利用 new Object 创建对象 2. 构造函数 【注意事项】 【例】 这样子写好之后&#xff0c;想要添加一个新的结构类似的对象&#xff0c;直接照着红圈中写&#xff0c;最后改相应的数据就好了 注意&#xff1a;红色是第一步&#xff0c;黄…