C++继承(全)

news2024/11/25 20:46:58

目录

继承

1.继承定义

2.继承方式和访问限定符

3.继承基类成员后,派生类相应的访问方式的变化

4.基类和派生类的对象赋值转换

1.切片或切割

2.赋值兼容

5.作用域

6.隐藏/重定义

派生类的默认成员函数

1.构造函数

2.拷贝构造函数

3.赋值运算符重载

4.析构函数

5.友元关系

6.静态成员

继承方式

1.单继承

2.多继承

3.菱形继承

4.菱形虚拟继承

1.菱形继承对象模型

2.菱形虚拟继承对象模型

5.虚基表指针

6.虚基表

继承和对象组合

小结


继承

1.继承定义

继承是使代码可以复用的重要手段,允许在原有类特性的基础上进行拓展,增加功能,这样产生的类叫做派生类。

Teacher:派生类

public:继承方式

Person: 基类

class Teacher:public Person
{
public:
    int _workid;
}

2.继承方式和访问限定符

3.继承基类成员后,派生类相应的访问方式的变化

总的来说:

1.对于基类的private成员:派生类中不可见。

2.对于public继承方式:基类是什么继承方式,子类就是什么访问方式(除开基类private成员)

3对于protected继承方式:子类都是protected访问方式(除开基类private的成员)

4对于private继承方式:子类都是private访问方式(除开基类private)

5.所以protected的出现就是为了让基类中的除private成员,在派生类中可以访问,但是在类内不能访问。

注意

1.class可以缺省继承方式,默认为private。struct默认为public

2.实际运用一般都是public继承,因为protected、private继承下,继承的成员只能在派生类中使用。

class Student:Person
{
    //.......
}

4.基类和派生类的对象赋值转换

1.切片或切割

派生类对象可以赋值给基类的对象,基类的指针,基类的引用。

        即派生类可以赋值给基类,因为派生类有的成员基类也有

        基类不能赋值给派生类(先暂时这样认为),因为派生类有的成员基类不一定有

在public继承下

相当于:每一个子类对象都是一个特殊的父类对象

class Person
{
public:

	void Pint()
	{
		cout << "name: " << _name << endl;
		cout << "age: " << _age << endl;
	}
	string _name;
	int _age;
};
class Student :public Person
{
	int _stdid;
};
class Teacher : public Person
{
	int _jobid;
};
void test1()
{
	Student st;
	Person p = st;
	//切割/切片赋值兼容
	Person& ref = st;//注意:这里可以不用加const,叫做赋值兼容
	Person* ptr = &st;
	ref._name += "xiao";
	ptr->_name += "ming";//可以改变子类
	st.Pint();
}

1.对于派生类赋值给基类的指针,指针指向的就是派生类的切片

2.派生类赋值给基类的引用,引用即派生类的切片

2.赋值兼容

注意:这里的引用不用const 叫做赋值兼容 (本来隐式类型转换会产生临时变量,临时变量具有常性)

5.作用域

同一个域中不能同名(除了函数重载)

函数重载:在同一个域才存在

1局部域

2全局域

1.2会影响生命周期

3命名空间域

4类域(衍生出:基类,派生类)是两个独立作用域

6.隐藏/重定义

1.当子类和父类有同名成员,子类成员将隐藏对父类的同名成员的直接访问

2.虽然直接访问不行,但是还是可以用 基类::基类成员 来间接访问

3.对于成员函数的隐藏,只要函数名字不同就构成隐藏(要区分:函数重载)

因为子类和父类是两个不同的作用域,就算函数名相同也不会构成重载

4.实际中一般不在继承体系中定义同名成员


class A
{
public:
	void fun()
	{
		cout << "func()" << endl;
	}
};
class B : public A
{
public:
	void fun(int i)
	{
		A::fun();
		cout << "func(int i)->" << i << endl;
	}
};
void test()
{
	B b;
	//b.fun();//调用参数过少
	b.fun(10);//调用B的
	b.A::fun();//调用A的
}

派生类的默认成员函数

把父类成员当作一个自定义类型(不能单独初始化父类的某个成员变量)

复习:

1.对于自定义类型在初始化时是在初始化列表初始化

2.不在初始化列表初始化:调用自定义类型的默认构造函数(没有就报错)

在初始化列表初始化:调用父类默认构造

1.构造函数

就像匿名对象,但不是匿名对象

本质是复用

Student2(int stdid, const string& name, int age)
		:_stdid(stdid)
		,Person2(name,age)
	{}

2.拷贝构造函数

这里直接传s就行,相当于切片、切割

本质是复用

Student2(const Student2&s)
		:Person2(s)//这里直接传s就行,相当于切片、切割
		,_stdid(s._stdid)
	{}

3.赋值运算符重载

这里直接传s就行,相当于切片、切割

注意要类域

Student2& operator=(const Student2& s)
	{
		if (&s != this)
		{
			Person2::operator=(s);
			_stdid = s._stdid;
		}
		return *this;
	}

4.析构函数


 因为后续析构的需要 析构函数名会统一处理成  ~destructor

子类析构会隐藏父类

~Student2()
	{
		//~Person2();报错  
		Person2::~Person2();
		//Person2::~Person2();
	}

相当于下面 (注意下面会报错)

~destructor()
	{
		Person2::~desturctor();//相当于构成隐藏
		~desturctor();
	}

5.友元关系

友元关系没有继承

基类的友元可以访问基类的私有和保护成员,但是不能访问派生类的私有和保护成员

6.静态成员

如果在基类定义的静态成员变量,那么这个继承体系只有一个静态成员,其所有派生类都只有一个static成员实例

继承方式

1.单继承

一个子类只有一个父类

2.多继承

一个子类有多个父类

3.菱形继承

是多继承的一种特殊情况

        存在数据冗余和二义性的问题

4.菱形虚拟继承

在继承关系前加上virtual

注意是对于指向同一个基类的派生类

class Person
{
public:
	string _name; 
};
class Student : virtual public Person 
{
protected:
	int _num; };
class Teacher : virtual public Person 
{
protected:
	int _id; 

1.菱形继承对象模型

这里的BC都有_a  ,存在数据冗余

2.菱形虚拟继承对象模型

虚拟继承解决数据冗余和二义性原理

5.虚基表指针

A为虚基类,虚基类放在最下面,变为公共的,派生类都有一个指针(叫做虚基表指针),指向的内容是偏移量,用偏移量计算虚基类的位置。

6.虚基表

这两个表就叫做虚基表

切片时指针偏移,指到自己对象的位置

继承和对象组合

public继承是is-a的关系,例如学生是人

对象组合是一种has-a的关系,例如汽车有轮胎

两者本质都是复用,但又不同点

注意要点:

1.优先使用对象组合,而非类继承

因为对于pubic继承,这种通过派生类的复用被称为:白箱复用(white-box reuse)

。因为在继承关系中,基类的内部细节对子类可见,基类和派生类有很强的依赖关系。

即低内聚,高耦合。

而对于对象组合,这种通过组合对象的复用一般叫做:黑箱复用(black-box reuse)

。因为在组合关系中,对象的内部细节是不可见的,组合类之间没有很强的依赖关系。

即低耦合,高内聚。

2.要实现多态也要继承。

继承:is-a例子

// Car和BMW Car和Benz构成is-a的关系
   class Car{
   protected:
   string _colour = "白色"; // 颜色
   string _num = "陕ABIT00"; // 车牌号
   };
   
   class BMW : public Car{
   public:
   void Drive() {cout << "好开-操控" << endl;}
   };
   
   class Benz : public Car{
   public:
   void Drive() {cout << "好坐-舒适" << endl;}
   };

组合:has-a关系


 

 // Tire和Car构成has-a的关系
   
   class Tire{
   protected:
       string _brand = "Michelin";  // 品牌
       size_t _size = 17;         // 尺寸
   
   };
   
   class Car{
   protected:
   string _colour = "白色"; // 颜色
   string _num = "陕ABIT00"; // 车牌号
    Tire _t; // 轮胎
   };

小结

1.什么是菱形继承?问题是?

菱形继承是多继承的一种特殊情况,两个子类继承同一个父类。

由于两个子类会有两个父类的成员,因此会造成数据冗余和二义性。

2.什么是菱形虚拟继承?如何解决数据冗余和二义性?

菱形虚拟继承是指在继承同一个父类的子类中用虚拟继承(virtua)的继承方式。

从而使基类的成员只储存一份,然后通过派生类的虚基表中的虚基表指针找到对应派生类与基类的偏移量,然后通过偏移量找到基类。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

怎么查苹果手机激活时间?立即get这3个方法

苹果手机的激活时间能帮助我们了解手机的购买时间和使用历史&#xff0c;对于二手交易也是一个重要的参考。然而&#xff0c;许多人可能不知道如何查看手机的激活时间。怎么查苹果手机激活时间&#xff1f;在本文中&#xff0c;我们将介绍三种简单而有效的方法&#xff0c;让您…

ros1 C++ 输出helloworld

1、创建工作空间并初始化 mkdir -p 自定义空间名称/src cd 自定义空间名称 catkin_make运行完&#xff0c;生成文件如下图&#xff1a; 2、进入 src 创建 ros 包并添加依赖 cd src catkin_create_pkg 自定义ROS包名 roscpp rospy std_msgs这里&#xff0c;我的自定义ROS包名…

回归预测 | Matlab实现DBO-HKELM蜣螂算法优化混合核极限学习机多变量回归预测

回归预测 | Matlab实现DBO-HKELM蜣螂算法优化混合核极限学习机多变量回归预测 目录 回归预测 | Matlab实现DBO-HKELM蜣螂算法优化混合核极限学习机多变量回归预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab实现DBO-HKELM蜣螂算法优化混合核极限学习机多变量…

现在开自助棋牌室,小心租房“陷阱”

之前分享了开自助棋牌室的市场调研流程&#xff0c;那就顺着开店步骤&#xff0c;我将每个环节细化干什么&#xff0c;做成笔记分享给小伙伴们&#xff01; 棋牌室大家在租房的时候&#xff0c;一定要注意以下这些地方&#xff0c;都是我们开了2家店之后&#xff0c;总结的血泪…

刚找到工作,碰到新项目,怎么入手?

之前有特训营老铁说&#xff0c;刚找到工作&#xff0c;碰到了新项目&#xff0c;没有头绪&#xff0c;该怎么入手&#xff1f; 10几年前&#xff0c;我刚入职单片机开发时&#xff0c;也慌得一批&#xff0c;在此之前&#xff0c;我只懂51单片机&#xff0c;玩过智能小车。 好…

SQLAIchemy 异步DBManager封装-01入门理解

前言 SQLAlchemy 是一个强大的 Python SQL 工具包和对象关系映射&#xff08;ORM&#xff09;系统&#xff0c;是业内比较流行的ORM&#xff0c;设计非常优雅。随着其2.0版本的发布&#xff0c;SQLAlchemy 引入了原生的异步支持&#xff0c;这极大地增强了其在处理高并发和异步…

codeforce #925 (div3) 题解

D. Divisible Pairs 给出数组 a a a&#xff0c;如果二元组 ( i , j ) (i,j) (i,j)满足 a i a j m o d x 0 & & a i − a j m o d y 0 a_i a_j mod x 0 \&\& a_i - a_j mod y 0 ai​aj​modx0&&ai​−aj​mody0&#xff0c;则beauty。其中 i &…

阿里云服务器项目部署docker-compose+vue+redis+nginx+minio+springboot

1 阿里云服务器项目部署-单机部署 docker-compose 1.1 搭建背景 服务器 阿里云服务器 前端 vue 后端 springboot 服务 redis 、nginx、minio 都做单机模式部署,不做集群部署 博客内容参考了其他博文&#xff0c;会贴出来 1.2 <重要>端口开放前提说明 任何开放的端…

2024年华中杯数学建模竞赛全攻略:ABC题思路解析+代码实现+数据集+论文撰写+全程答疑

引言 &#xff08;比赛后所有题目资料在文末获取呀&#xff09; 华中杯数学建模竞赛是数学建模领域的一项重要赛事&#xff0c;它不仅考验参赛者的数学建模能力&#xff0c;还考验了编程技能、数据分析能力和论文撰写能力。为了帮助参赛者更好地准备2024年的竞赛&#xff0c;本…

编程填空题:麻烦的位运算

闲着没事干可以做做 可以看到&#xff0c;那个函数直接return了&#xff0c;也就是说&#xff0c;得找到一个表达式&#xff0c;直接求出结果 简单分析一下&#xff1a; 其第i位为1当且仅当n的右边i位均为1 也就是说&#xff0c;前i-1位有0&#xff0c;第i位就是0 也就是说…

二维数组之前缀和中篇

在此之前&#xff0c;可以先看看这篇二维数组之二维前缀和-首篇。 和为K的子数组 给你一个整数数组 nums 和一个整数 k &#xff0c;请你统计并返回 该数组中和为 k 的子数组的个数 。子数组是数组中元素的连续非空序列。 示例 1&#xff1a; 输入&#xff1a;nums [1,1,…

cesium加载倾斜影像数据(模拟雨、雪、雾、无人机飞行、测距、箭头标绘、电子围栏等)

实现效果如下&#xff1a; 功能菜单如下&#xff1a; 加载倾斜影像核心代码&#xff1a; var palaceTileset new Cesium.Cesium3DTileset({url: http://127.0.0.1:9002/tileset.json,//控制切片视角显示的数量&#xff0c;可调整性能maximumScreenSpaceError: 0.1,maximumNum…

c++的学习之路:25、map与set

摘要 本文中说一下map与set的使用 目录 摘要 一、关联式容器 二、键值对 三、map 1、map的介绍 2、map的使用 1、map的模板参数说明&#xff1a; 2、map的构造 3、map的迭代器 4、map的容量与元素访问 5、map中元素的修改 6、代码使用 ​编辑 三、总结 四、se…

51单片机入门_江协科技_33~34_OB记录的自学笔记_LED呼吸灯与PWM直流马达调速

33. 直流电机驱动(PWM) 33.1. 直流电机介绍 •直流电机是一种将电能转换为机械能的装置。一般的直流电机有两个电极&#xff0c;当电极正接时&#xff0c;电机正转&#xff0c;当电极反接时&#xff0c;电机反转 •直流电机主要由永磁体&#xff08;定子&#xff09;、线圈&…

winform 入门篇 -- 第15章 表格视图

表格控件 表格视图 DataGridView &#xff0c;即表格控件提行多行多列的表格状的数据展示 演示: 以表格控件来展示学生数据。。 每个单元格 都可以进行独立的编写 &#xff08;与上节得不同&#xff09; 基本操作: 1 添加一个表格控件 DataGridView 2 设置列数、列名 属…

HarmonyOS Next 视频弹幕功能

视频弹幕功能 介绍 本示例介绍如何使用ohos.danmakuflamemaster和ohos.gsyvideoplayer开发支持视频弹幕的播放器。可以自定义弹幕样式、占据屏幕宽度&#xff0c;发送弹幕&#xff0c;开关弹幕视图。 效果图预览 使用说明 点击播放按钮&#xff0c;进行视频播放&#xff0c…

STM32 USB虚拟串口

电路原理图 usb部分 晶振部分 usb与单片机连接 配置信息 sys配置信息 rcc配置信息 usb配置信息 虚拟串口配置信息 时钟配置信息 项目配置信息 代码 包含文件 主函数代码 实验效果 修改接收波特率依然可以正常接收&#xff0c;也就是说单片机可以自动适应上位机的波特率设置。…

2023年图灵奖揭晓:Avi Wigderson的辉煌成就与深远影响

2023年图灵奖揭晓&#xff0c;你怎么看&#xff1f; 2023年图灵奖&#xff0c;最近刚刚颁给普林斯顿数学教授 Avi Wigderson&#xff01;作为理论计算机科学领域的领军人物&#xff0c;他对于理解计算中的随机性和伪随机性的作用&#xff0c;作出了开创性贡献。 方向三&#xf…

免费泛域名SSL如何申请,和通配符有什么区别

-----让我们明确什么是泛域名。所谓泛域名&#xff0c;是指使用星号&#xff08;*&#xff09;作为子域名的占位符&#xff0c;它可以匹配任意子域名。-----而通配符在域名中&#xff0c;它可以出现在主域名的任何位置&#xff0c;它可以用于主域名和子域名的保护。 主要应用场…

握手问题(蓝桥杯)

文章目录 握手问题【问题描述】答案&#xff1a;1204解题思路模拟 握手问题 【问题描述】 小蓝组织了一场算法交流会议&#xff0c;总共有 50 人参加了本次会议。在会议上&#xff0c;大家进行了握手交流。按照惯例他们每个人都要与除自己以外的其他所有人进行一次握手&#…