继承【C/C++复习版】

news2024/11/22 13:55:35

目录

一、什么是继承?怎么定义继承?

二、继承关系和访问限定符?

三、基类和派生类对象可以赋值转换吗?

四、什么是隐藏?隐藏vs重载?

五、派生类的默认成员函数?

1)派生类构造函数怎么写?

2)派生类拷贝构造函数怎么写?

3)派生类operator=怎么写?

4)派生类析构函数怎么写?☆☆

六、什么是友元?友元关系能继承吗?

七、静态成员和继承的关系? 

八、什么是多继承,多继承的坑是什么?

九、如何解决菱形继承的问题? 

十、菱形虚拟继承的原理是什么?


一、什么是继承?怎么定义继承?

当多个类之间有许多共同的方法或属性时,可以将这些方法和属性提取出来作为一个父类,让子类通过继承父类来进行代码的复用,同时,子类也可以在父类的基础上做一些扩展。

怎么定义:

class 派生类名:继承方式(public/protected/private) 基类名
{
public:
    int _n;
};

//eg:
class Student:public Person{
public:
    int _stuid;
};

二、继承关系和访问限定符?

1)首先对于基类的私有成员,无论以什么方式继承,在类外以及派生类内都是不可见的。

2)对于基类的公有成员保护成员

公有继承:基类所有成员保持原有访问权限。

保护继承:基类的公有成员访问权限变成保护

私有继承:基类的公有成员和保护成员访问权限变成私有

 三、基类和派生类对象可以赋值转换吗?

1)向上转换:派生类对象/指针可以赋值给基类的对象/指针/引用,这种情况也叫切片(只看到基类中的部分)。

!!注意:只有公有继承才有可能直接进行基类和派生类之间的赋值转换,私有和保护继承改变了派生类对基类的访问权限,使得无法直接进行类型转换。

2)向下转换:基类对象不能赋值给派生类对象。基类指针类型或基类引用类型如果原本是指向派生类的,那么它可以赋值给派生类指针类型或派生类引用类型,但需要手动强制类型转换。

class Base {
private:
    int private1;
};

class Pai1 : public Base{
private:
    int p1;
};

int main()
{
    Pai1 p;
    Base b;
    b = p;
    Base& rb = p;
    Base* pb = &p;

    Pai1* pp = (Pai1*)pb;
    Pai1& rp = (Pai1&)rb;
}

 四、什么是隐藏?隐藏vs重载?

在继承体系中基类和派生类的作用域是独立的,如果在基类和派生类中出现了同名成员,子类将屏蔽父类同名成员,直接访问自己的,这就叫隐藏。如果是成员函数,只要函数名相同,就构成隐藏(也叫重定义)。

如果子类想要访问父类的同名成员,可以指定类域。

class A {
public:
	void fun(){
		std::cout << "A" << std::endl;
	}
};
class B : public A{
	void fun(){
		A::fun();
		std::cout << "B" << std::endl;
	}
};

隐藏和重载的区别在于:隐藏是在不同的作用域的,重载是在同一作用域下的。且重载的限制条件更多,不仅要求函数同名,且形参列表必须不同。

 五、派生类的默认成员函数?

1)派生类构造函数怎么写?

派生类必须调用父类构造函数来初始化父类成员。

1)父类有默认构造,派生类构造时会自动调用父类默认构造。

2)父类没有默认构造,需要在派生类构造函数的初始列表显示调用父类构造函数。

class Person {
public:
	Person(string name)
	:_name(name)
	{}
private:
	string _name;
};
class Student :public Person{
public:
	Student(string name,int num)
	:Person(name)
	,_num(num)
	{}
private:
	int _num;
};

2)派生类拷贝构造函数怎么写?

调用父类的拷贝构造,可以传子类的对象给父类拷贝构造,构成切片。然后再实现自己的部分。

不显示写的话会调父类的默认构造而不是拷贝构造,所以不能不显示调用。

	Student(const Student& stu)
	:Person(stu)
	,_num(stu._num)
	{}

3)派生类operator=怎么写?

 要显示调用父类的operator=,再实现自己的部分。

	Student& operator=(const Student& stu)
	{
		if (this != &stu) {
			Person::operator=(stu);//调用父类的
			_num = stu._num;
		}
		return *this;
	}

4)派生类析构函数怎么写?☆☆

 派生类的析构函数不需要我们手动调用,因为它要保证先析构子类,再析构父类。以防出现析构完父类后,子类又用到父类成员的情况。让编译器来做这件事比让人来做更靠谱。

六、什么是友元?友元关系能继承吗?

如果一个函数或一个类想访问某一个类A的保护成员或私有成员,可以在类A中声明一下:

 注意:友元关系不能继承!!!

七、静态成员和继承的关系? 

静态成员不属于某个类或对象,它是在静态区中保存的,只有一份,但它是受类的访问限定符的约束的。子类继承的是静态成员的使用权。

静态成员变量必须在类内声明,类外定义和初始化

静态成员函数的定义和初始化可以在类内也可以在类外。

class MyClass {
public:
    static int staticVar; // 在类内声明静态成员变量
    static void staticFunc() {
        // 在类内定义静态成员函数,可以直接实现功能
    }
};

int MyClass::staticVar = 0; // 在类外定义静态成员变量并进行初始化

八、什么是多继承,多继承的坑是什么?

一个人是可能有多重角色的,那么有多个父类也是合理的。

但是,有了多继承,就有可能出现菱形继承,菱形继承会引发很多问题:

① 二义性(Assistant对象中访问的_name到底访问的是从哪个类中继承的?)

② 数据冗余(浪费空间)

九、如何解决菱形继承的问题? 

1)二义性:可以通过指定类域来访问,这种方式虽然表面上解决了二义性的问题,但它其实是违背了现实世界的。

2)更根本地解决数据冗余和二义性的做法是:虚继承

给菱形继承中继承了同一个类的类都加上virtual关键字。

class Student:virtual public Person
{
    //...
}
class Teacher:virtual public Person
{
    //...
}

十、菱形虚拟继承的原理是什么?

继承了同一个类的这些类加了virtual关键字后,这些类会多一个成员,这个成员的类型是虚基表的指针,指向的是一张虚基表,虚基表里保存是距离父类的成员的偏移量。

思考一下:D对象赋值给B对象的切片,B*pb = &d; pb->_a可以正常访问吗?

为什么不直接存偏移量?

虚基表除了存偏移量可能还会存别的值,在对象中存虚基表的指针可以保证每个对象只需要多存一个指针大小即可。

在下面的例子中,A的构造会调用几次?ABCD谁先构造?

十一、继承和组合的区别?什么时候用继承,什么时候用组合?

组合是指一个类持有另一个类的实例作为自己的属性,通过调用被组合对象的方法实现功能。组合是一种"has a"关系,即一个对象包含另一个对象。

在选择使用继承还是组合时,通常遵循以下原则:

- 当两个类之间有明显的"is a"关系,即子类是父类的一种特殊形式时,可以使用继承。

- 当两个类之间有“has a”关系,即一个类包含另一个类作为属性时,可以使用组合。

继承时一种白箱复用,其内部的细节对子类是可见的,组合是一种黑箱复用,对象内部细节是不可见的。尽量避免过度使用继承,因为过度继承可能导致类之间的耦合度过高,影响代码的灵活性和可维护性。因此在设计时需要根据具体的情况选择合适的方式来设计类之间的关系。

 

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

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

相关文章

JVM基础:类的生命周期详解

JDK版本&#xff1a;jdk8 IDEA版本&#xff1a;IntelliJ IDEA 2022.1.3 文章目录 一. 生命周期概述二. 加载阶段(Loading)2.1 加载步骤2.2 查看内存中的对象 三. 连接阶段(Linking)3.1 连接之验证3.2 连接之准备3.3 连接阶段之解析 四. 初始化阶段(Initialization)4.1 单个类的…

vivado 使用基本触发器模式

使用基本触发器模式 基本触发器模式用于描述触发条件 &#xff0c; 即由参与其中的调试探针比较器组成的全局布尔公式。当“触发器模式 (Trigger Mode) ”设置为 BASIC_ONLY 或 BASIC_OR_TRIG_IN 时 &#xff0c; 即启用基本触发器模式。使用“基本触发器设置 (Basic Trig…

软件测试级别和对应要求

软件测试级别指的是将软件测试活动按照不同的开发阶段和测试目的进行分类&#xff0c;形成不同层次的测试过程。 分级依据&#xff0c;根据V模型 单元测试&#xff1a;这是软件生命周期中的第一个测试级别&#xff0c;主要针对软件的最小单元模块进行&#xff0c;例如类、函数…

二叉树学习

树 树是n个结点的有限集合&#xff0c;当n0时为空树&#xff0c;在任意一颗非空的树中&#xff0c;有且只有一个特定的称为根的结点&#xff0c;当n>1时&#xff0c;其余结点又可以分为m个不相交的有限集&#xff0c;其中每一个集合又是一棵树&#xff0c;并且称为根的子树…

opencv 多线程读取和显示摄像头【python源码】

在Python中&#xff0c;使用OpenCV库实现多线程读取和显示摄像头通常涉及创建多个线程&#xff0c;每个线程负责从摄像头捕获视频帧并显示它们。但是&#xff0c;请注意&#xff0c;OpenCV本身并不直接支持多线程显示&#xff0c;因为cv2.imshow通常是在主线程中运行的。然而&a…

imu6xl点灯(C语言)

参考正点原子开发指南 根据原理图可以看出&#xff0c;我们需要设置低电平导通电路。 在原理图上找到LED0&#xff0c;对应IO为GPIO3 IO复用配置 IMX6UL每个引脚都可以复用 在用户手册第30章可以找到IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03这个寄存器&#xff0c;地址为0x020E0068&…

JavaScript函数式编程

函数式编程 课程介绍 为什么要学习函数编程以及什么是函数式编程函数式编程的特性(纯函数、柯里化、函数组合等)函数式编程的应用场景函数式编程库Lodash 为什么要学习函数式编程 函数式编程是非常古老的一个概念&#xff0c;早于第一台计算机的诞生&#xff0c; 函数式编程…

gpt系列概述——从gpt1到chatgpt

GPT建模实战&#xff1a;GPT建模与预测实战-CSDN博客 OpenAI的GPT&#xff08;Generative Pre-trained Transformer&#xff09;系列模型是自然语言处理领域的重要里程碑。从2018年至2020年&#xff0c;该公司相继推出了GPT-1、GPT-2和GPT-3&#xff0c;这些模型在文本生…

是时候将 DevOps 可见性扩展到网络边缘了

尽管部署前运行了大量测试&#xff0c;但在部署应用程序后&#xff0c;性能问题经常让 DevOps 团队感到困惑。经过进一步调查&#xff0c;最常被忽视的问题是应用程序本身的分布式特性。从多个位置访问应用程序的最终用户永远不会拥有相同水平的互联网服务&#xff0c;因此在纽…

python使用ffmpeg分割视频为Hls分片文件/使用OpenSSL加密m3u8和TS文件

FFmpeg和OpenSSL是一个开源免费的软件&#xff0c;在官网上就能下载&#xff0c; FFmpage网址&#xff08;建议选择文件名full结尾的文件&#xff09;&#xff1a;Builds - CODEX FFMPEG gyan.dev OpenSSL网址&#xff08;建议选择win64的MSI文件&#xff09;&#xff1a;Win3…

OpenAI现已普遍提供带有视觉应用程序接口的GPT-4 Turbo

OpenAI宣布&#xff0c;其功能强大的GPT-4 Turbo with Vision模型现已通过公司的API全面推出&#xff0c;为企业和开发人员将高级语言和视觉功能集成到其应用程序中开辟了新的机会。 PS&#xff1a;使用Wildcard享受不受网络限制的API调用&#xff0c;详情查看教程 继去年 9 月…

LinkedHashMap部分底层源码解析

JDK版本为1.8.0_271&#xff0c;LinkedHashMap继承了HashMap&#xff0c;LinkedHashMap在HashMap的基础上维护了一个双向链表&#xff0c;实现了可以根据插入顺序/访问顺序&#xff08;accessOrderfalse/true&#xff09;访问Map集合。 关于HashMap的原理可以参考HashMap部分底…

IOPaint部署,实现去水印效果

下载源代码 https://github.com/Sanster/IOPaint https://github.com/advimman/lama 创建虚拟环境 conda create --prefixD:\CondaEnvs\iopaint python3.10 conda activate D:\CondaEnvs\iopaint安装依赖包 pytorch最低2.0.0 # 查看cuda版本安装对应的pytorch nvcc -V # …

Prototype 原型

意图 用原型实例指定创建对象的种类&#xff0c;并且通过复制这些原型创建新的对象。 结构 Prototype声明一个复制自身的接口。ConcretePrototype实现一个复制自身的操作。Client让一个原型复制自身从而创建一个新的对象。 适用性 当一个系统应该独立于他的产品创建、构成和…

HashMap的常见问题

Entry中的hash属性为什么不直接使用key的hashCode()返回值呢&#xff1f; 不管是JDK1.7还是JDK1.8中&#xff0c;都不是直接用key的hashCode值直接与table.length-1计算求下标的&#xff0c;而是先对key的hashCode值进行了一个运算&#xff0c;JDK1.7和JDK1.8关于hash()的实现…

如何卸载干净 IDEA(图文讲解)

更新时间 2022-12-20 11:一则或许对你有用的小广告 星球 内第一个项目&#xff1a;全栈前后端分离博客项目&#xff0c;演示地址&#xff1a;Weblog 前后端分离博客, 1.0 版本已经更新完毕&#xff0c;正在更新 2.0 版本。采用技术栈 Spring Boot Mybatis Plus Vue 3.x Vit…

lanqiao.602 迷宫

题目&#xff1a; 代码&#xff1a; #include<iostream> #include<cstring> #include<algorithm> #include<queue> using namespace std; char mp[31][51]; //稍微开大一点 char k[4]{D,L,R,U}; //按字典序记录路径 int dirx[]{1,0,0,-1},d…

给picgo上传的图片加个水印

之前给大家介绍了picgo和免费的图床神器。我们本可以开开心心的进行markdown写作了。 但是总是会有那么一些爬虫网站过来爬你的文章&#xff0c;还把你的文章标明是他们的原著。咋办呢&#xff1f;这里有一个好的办法就是把markdown中上传的图片加上自己的水印不就行了。 说干…

【复现】CVE-2024-29269 某国外路由器RCE漏洞_72

目录 一.概述 二 .漏洞影响 三.漏洞复现 1. 漏洞一&#xff1a; 四.修复建议&#xff1a; 五. 搜索语法&#xff1a; 六.免责声明 一.概述 在 Telesquare TLR-2005Ksh 1.0.0 和 1.1.4 中发现的一个问题允许攻击者通过 Cmd 参数运行任意系统命令。 二 .漏洞影响 通过提交…

C语言---顺序表(二)

文章目录 前言1.准备工作2.代码的实现2.1.顺序表的创建、销毁和打印2.2.顺序表的扩容、头插\删、尾插\删2.2.1.扩容2.2.2.尾插2.2.3.头插2.2.3.尾删2.2.4.头删 2.3.指定位置之前插入/删除数据/查找数据2.3.1.指定位置之前插入数据2.3.2.指定位置之前删除数据2.3.3.查找特定数据…