【C++进阶之路】继承与多态的概念考察

文章目录

  • 一、问答题
  • 二、概念题
  • 三、答案与解析
    • 问答题
    • 概念题

一、问答题

  1. 什么是菱形继承?菱形继承的问题是什么?
  2. 什么是菱形虚拟继承?如何解决数据冗余和二义性的。
  3. 继承和组合的区别?什么时候用继承?什么时候用组合?
  4. 什么是多态?
  5. 什么是重载、重写(覆盖)、重定义(隐藏)?
  6. 多态的实现原理?
  7. inline函数可以是虚函数吗?
  8. 静态成员可以是虚函数吗?
  9. 构造函数可以是虚函数吗?
  10. 析构函数可以是虚函数吗?
  11. 对象访问普通函数快还是虚函数更快?
  12. 虚函数表是在什么阶段生成的,存在哪的?
  13. C++菱形继承的问题?虚继承的原理?
  14. 什么是抽象类?抽象类的作用?

二、概念题

  1. 下面哪种面向对象的方法可以让你变得富有( )
    A: 继承 B: 封装 C: 多态 D: 抽象

  1. ( )是面向对象程序设计语言中的一种机制。这种机制实现了方法的定义与具体的对象无关,而对方法的调用则可以关联于具体的对象。
    A: 继承  B: 模板  C: 对象的自身引用  D: 动态绑定

  1. 面向对象设计中的继承和组合,下面说法错误的是?()
    A:继承允许我们覆盖重写父类的实现细节,父类的实现对于子类是可见的,是一种静态复用,也称为白盒复用
    B:组合的对象不需要关心各自的实现细节,之间的关系是在运行时候才确定的,是一种动态复用,也称为黑盒复用
    C:优先使用继承,而不是组合,是面向对象设计的第二原则
    D:继承可以使子类能自动继承父类的接口,但在设计模式中认为这是一种破坏了父类的封装性的表现

  1. 以下关于纯虚函数的说法,正确的是( )
    A:声明纯虚函数的类不能实例化对象
    B:声明纯虚函数的类是虚基类
    C:子类必须实现基类的纯虚函数
    D:纯虚函数必须是空函数

  1. 关于虚函数的描述正确的是( )
    A:派生类的虚函数与基类的虚函数具有不同的参数个数和类型
    B:内联函数不能是虚函数
    C:派生类必须重新定义基类的虚函数
    D:虚函数可以是一个static型的函数

  1. 关于虚表说法正确的是( )
    A:一个类只能有一张虚表
    B:基类中有虚函数,如果子类中没有重写基类的虚函数,此时子类与基类共用同一张虚表
    C:虚表是在运行期间动态生成的
    D:一个类的不同对象共享该类的虚表

  1. 假设A类中有虚函数,B继承自A,B重写A中的虚函数,也没有定义任何虚函数,则( )
    A:A类对象的前4个字节存储虚表地址,B类对象前4个字节不是虚表地址
    B:A类对象和B类对象前4个字节存储的都是虚基表的地址
    C:A类对象和B类对象前4个字节存储的虚表地址相同
    D:A类和B类虚表中虚函数个数相同,但A类和B类使用的不是同一张虚表

  1. 下面程序输出结果是什么? ()
#include<iostream>
using namespace std;
class A{
public:
	A(char *s) { cout<<s<<endl; }
	~A(){}
};

class B:virtual public A
{
public:
	B(char *s1,char*s2):A(s1) { cout<<s2<<endl; }
};

class C:virtual public A
{
public:
	C(char *s1,char*s2):A(s1) { cout<<s2<<endl; }
};

class D:public B,public C
{
public:
	D(char *s1,char *s2,char *s3,char *s4):B(s1,s2),C(s1,s3),A(s1)
	{ cout<<s4<<endl;}
};

int main() {
	D *p=new D("class A","class B","class C","class D");
	delete p;
	return 0;
}

A:class A class B class C class D
B:class D class B class C class A
C:class D class C class B class A
D:class A class C class B class D


  1. 多继承中指针偏移问题?下面说法正确的是( )
class Base1 { public: int _b1; };
class Base2 { public: int _b2; };
class Derive : public Base1, public Base2 { public: int _d; };
int main(){
Derive d;
Base1* p1 = &d;
Base2* p2 = &d;
Derive* p3 = &d;
return 0;
}

A:p1 == p2 == p3
B:p1 < p2 < p3
C:p1 == p3 != p2
D:p1 != p2 != p3


  1. 以下程序输出结果是什么()
class A
{
public:
	virtual void func(int val = 1){ std::cout<<"A->"<< val <<std::endl;}
	virtual void test(){ func();}
};
class B : public A
{
public:
	void func(int val=0){ std::cout<<"B->"<< val <<std::endl; }
};
int main(int argc ,char* argv[])
{
	B*p = new B;
	p->test();
	return 0;
}

A: A->0
B: B->1
C: A->1
D: B->0
E: 编译出错
F: 以上都不正确

三、答案与解析

问答题

  1. 什么是菱形继承?菱形继承的问题是什么?
    解析:菱形继承是多继承延伸出来的问题,可概括为"一子多父,多父共一父",这样导致了数据冗余和二义性问题,最关键的在于数据冗余,如果数据量过大,则会导致内存资源浪费的问题,二义性可通过指定作用域来解决。

  2. 什么是菱形虚拟继承?如何解决数据冗余和二义性的。
    解析:从概念上来讲,菱形虚拟继承是在菱形继承的基础上,在父类继承其基类时,前加virtual的现象,从原理上来讲,通过引用虚基表和虚基表指针,加以改变对象的存储模型,使最后一个位置存的是基类,原来存基类的位置换成了虚基表指针,虚基表指针指向的是虚基表,虚基表存放的是偏移量,第一个位置存放的是虚基表指针的地址相对于this指针的偏移量,计算方式:this指针 - 虚表指针的地址(通常为0或者-4),第二个位置存放的是虚基表指针的地址相对于基类的this指针 的偏移量,第三个位置存放的可能是相较于其它基类的偏移量。最后一个位置存放的是结束位置,VS下为0。这只是一个元素要存放的信息。通过如上操作,虚表和虚基表指针来达到节省内存空间的值,总的来说还是浪费几个字节的,不过相较于数据量很大的来说就忽略不计了,其次这样设计是为了考虑通用性,一个类直接用一张统一的虚基表和虚表指针即可。

  3. 继承和组合的区别?什么时候用继承?什么时候用组合?
    解析:在实现类的多态时,我们就不得不使用继承了,因为只有继承才能实现类的多态。在大多数情况下,能考虑用组合就用组合,因为组合更加符合高内聚低耦合的概念,使代码之间更加地完整和独立。

  4. 什么是多态?
    解析:从概念上来讲,就是一种事物对应不同种形态,符合 has_a的关系,从分类上来讲,多态分为函数重载和动态绑定,从实现角度上来讲,主要是通过基类的指针和引用以及虚函数和重写,来达到通过父类的指针或引用指向子类时,能够调用子类的虚函数而不是父类的虚函数。

  5. 什么是重载、重写(覆盖)、重定义(隐藏)?
    一张图理解:
    在这里插入图片描述

  6. 多态的实现原理?
    解析:从实现角度上来讲,主要是通过基类的指针和引用以及虚函数和重写,来达到通过父类的指针或引用指向子类时,能够调用子类的虚函数而不是父类的虚函数。

  7. inline函数可以是虚函数吗?
    解析: 这里我们要明确两个概念的区别内联函数和被inline关键字修饰的函数,被inline修饰的函数最终是不是内联是我们说了不算的,最终要靠编译器来决定的,虚函数前加inline并不是内联,因为如果是内联,那虚函数的地址就不会被存放在虚表中,而我们都知道虚函数是要存放在虚表中的,与概念相悖,因此虚函数可以被inline修饰,但是其不是内联函数。

  8. 静态成员可以是虚函数吗?
    解释:不是,因为静态成员没有this指针,仅通过对象和指定作用域调用即可,而多态调用是要传this指针,通过this指针来判断是否构成多态的条件,从而实现多态,因此不可能是虚函数。

  9. 构造函数可以是虚函数吗?
    解释:不可以,从语法上编译器就禁掉了,从原理层上来看,我们要考虑先有鸡还是先有蛋的问题,即先初始化虚表指针(蛋)再调用构造函数(鸡)。这是不现实的,因此只能通过构造函数初始化函数指针,在通过虚函数指针调用虚函数。

  10. 析构函数可以是虚函数吗?
    解释:可以,我们也推荐加上virtual,在实现多态时,如果不是虚函数,从而导致指向子类的父类指针,在进行delete时,只调用了父类的析构而没有调用子类的析构函数,这样可能会导致内存泄漏,因此可以,并强烈建议加上。

  11. 对象访问普通函数快还是虚函数更快?
    解释:普通函数在调用时,是直接call对应的函数地址,而虚函数需要先找到虚函数指针,再通过虚函数指针找到对应的地址,再进行调用,因此普通函数更快,但综合下来只在函数过多的情况下考虑这种问题,一般来说差别不大。

  12. 虚函数表是在什么阶段生成的,存在哪的?
    解释:虚函数表是在编译期间生成的,至少在VS下是存在常量区的。

  13. 什么是抽象类?抽象类的作用?
    解释:我们把具有纯虚函数的类称为抽象类,抽象类在运用角度来说,强制子类必须重写虚函数,否则无法进行示例化,因为继承了纯虚函数是无法示例化的。

概念题

在这里插入图片描述

  1. A 2. D 3. C 4. A 5. B
  2. D 7. D 8. A 9. C 10. B

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

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

相关文章

linux基于信号量实现多线程生产者消费者模型

基于信号量实现多线程生产者消费者模型。 编程思路&#xff1a; 1.食物的初始化编号为100&#xff1a; beginnum 100&#xff1b; 2.仓库有5个空碗&#xff0c;最多保存5个食物&#xff1a;queue[5]&#xff1b; 3.初始化空碗的数量为5&#xff0c;食物的数量为0&#xff1a…

FFmpeg中AVIOContext的使用

通过FFmpeg对视频进行编解码时&#xff0c;如果输入文件存在本机或通过USB摄像头、笔记本内置摄像头获取数据时&#xff0c;可通过avformat_open_input接口中的第二个参数直接指定即可。但如果待处理的视频数据存在于内存块中时&#xff0c;该如何指定&#xff0c;可通过FFmpeg…

《孙子兵法》快速概览,有哪些章节?趣讲《孙子兵法》【第2讲】

《孙子兵法》快速概览&#xff0c;有哪些章节&#xff1f;趣讲《孙子兵法》【第2讲】 《孙子兵法》十一家注是一个有名的版本&#xff0c;十一家注是曹操、杜牧等十一人注释&#xff0c;曹操是真正的军事家&#xff0c;是名副其实的大咖。总共三卷十三篇&#xff0c;比较难记住…

3个月快速入门LoRa物联网传感器开发

在这里插入图片描述 快速入门LoRa物联网传感器开发 LoRa作为一种LPWAN(低功耗广域网络)无线通信技术,非常适合物联网传感器和行业应用。要快速掌握LoRa开发,需要系统学习理论知识,并通过实际项目积累经验。 摘要: 先学习LoRa基础知识:原理、网络架构、协议等,大概需要2周时间…

Java加密算法的应用与实现(MD5、SHA、DES、3DES、AES、RSA、ECC)

文章目录 一、散列加密算法1、概述2、常见算法&#xff08;MD5、SHA&#xff09;3、应用4、Java实现 二、对称加密算法1、概述2、常见算法&#xff08;DES、3DES、AES&#xff09;3、应用4、Java实现AES 三、非对称加密算法1、概述2、常见算法&#xff08;RSA、ElGamal、Rabin、…

【linux】ssh 和adb connect区别

问&#xff1a;ssh 与ping的区别 答&#xff1a;SSH&#xff08;Secure Shell&#xff09;和Ping是两种完全不同的网络工具。 SSH是一种加密的网络协议&#xff0c;用于安全地远程管理或访问远程计算机。它提供了一种安全的通信方式&#xff0c;可以在不安全的网络上进行远程登…

淘宝API接口为开发者提供了与淘宝平台进行数据交互和操作的便捷途径

淘宝API接口是指淘宝开放平台提供的一套接口&#xff0c;用于与淘宝网进行数据交互和操作。通过使用淘宝API接口&#xff0c;第三方开发者可以实现商品搜索、店铺信息获取、订单管理、商家服务等功能&#xff0c;从而实现与淘宝平台的对接和数据共享。 淘宝API接口的使用可以帮…

备忘录模式(Memento)

备忘录模式是一种行为设计模式&#xff0c;在不破坏封装性的前提下&#xff0c;允许在不暴露对象实现细节的情况下保存和恢复对象之前的状态。 Memento is a behavior design pattern. Without compromising encapsulation, it can reserve and restore of the previous stat…

vscode自动添加注释说明

1. 安装vscode 双击安装程序,默认安装即可(如:VSCodeSetup-x64-1.70.2.exe) 2. 安装doxygen文档生成插件 1> 打开vscode软件,点击左侧插件管理菜单 2> 点击右上角’…‘按钮,选择’Install from VSIX’(联网状态可以直接搜索doxygen下载安装) 3> 选择doxygen离线安装…

Java课题笔记~ 使用 Spring 的事务注解管理事务(掌握)

通过Transactional 注解方式&#xff0c;可将事务织入到相应 public 方法中&#xff0c;实现事务管理。 Transactional 的所有可选属性如下所示&#xff1a; propagation&#xff1a;用于设置事务传播属性。该属性类型为 Propagation 枚举&#xff0c; 默认值为 Propagation.R…

【SpringBoot】日志是什么+基于lombok的日志输出

博主简介&#xff1a;想进大厂的打工人博主主页&#xff1a;xyk:所属专栏: JavaEE进阶 在我们日常的程序开发中&#xff0c;日志是程序的重要组成部分&#xff0c;想象⼀下&#xff0c;如果程序报错了&#xff0c;不让你打开控制台看⽇志&#xff0c;那么你能找到报错的原因吗…

BEM命名规范

参加了一个团队开发的小项目&#xff0c;代码写完了一看别人的感觉自己写的老不规范了&#xff0c;后知后觉才看到开发文档里面的样式书写规范。感觉要大改了……也算给自己长个记性要先读完所有文档在开始。 也学习了解了一下BEM命名规范。 1. 什么是BEM&#xff1f; BEM&a…

软件测试(功能、接口、性能、自动化)详解

一、软件测试功能测试 测试用例编写是软件测试的基本技能&#xff1b;也有很多人认为测试用例是软件测试的核心&#xff1b;软件测试中最重要的是设计和生成有效的测试用例&#xff1b;测试用例是测试工作的指导&#xff0c;是软件测试的必须遵守的准则。 黑盒测试常见测试用…

MinIO:微服务中上传图片流程

1、在nacos中配置minio参数 2、controller层 package com.heima.wemedia.controller.v1;import com.heima.model.common.dtos.ResponseResult; import com.heima.wemedia.service.WmMaterialService; import org.springframework.beans.factory.annotation.Autowired; import …

用栈判断是否匹配

1 问题 写代码的时候用到的括号都是成双成对的出现&#xff0c;并且大小也相同。在集成编辑环境中&#xff0c;IDE就会为我们自己动检查括号是否匹配。那么为了避免在报错&#xff0c;如何判断是否有无括号不匹配&#xff1f; 2 方法 利用栈来实现这种功能。当遇见一个左括号&a…

SpringCloud-Hystrix服务熔断与降级工作原理源码 | 京东物流技术团队

先附上Hystrix源码图 在微服务架构中&#xff0c;根据业务来拆分成一个个的服务&#xff0c;服务与服务之间可以相互调用&#xff08;RPC&#xff09;&#xff0c;在Spring Cloud可以用RestTemplateRibbon和Feign来调用。为了保证其高可用&#xff0c;单个服务通常会集群部署。…

代码随想录算法训练营day59

文章目录 Day59 下一个更大元素II题目思路代码 接雨水题目思路代码 Day59 下一个更大元素II 503. 下一个更大元素 II - 力扣&#xff08;LeetCode&#xff09; 题目 给定一个循环数组&#xff08;最后一个元素的下一个元素是数组的第一个元素&#xff09;&#xff0c;输出每…

UNIX网络编程卷一 学习笔记 第二十七章 IP选项

IPv4允许在20字节的首部固定部分后跟最多共40字节的选项。尽管已经定义了10种IPv4选项&#xff0c;但最常用的是源路径选项。我们可通过存取IP_OPTIONS套接字选项访问这些选项&#xff0c;我们存取该套接字选项时&#xff0c;所用的缓冲区中的值就是它们置于IP数据报中的格式。…

第二课-一键安装SD-Stable Diffusion 教程

前言 看完这篇文章并跟着操作,就可以在本地开始 SD 绘图了。 理论上来说,这篇课程结束,想要画什么图都可以画了。 启动器介绍 SD 是开源的,可以在 github 上找到。但直接下载源码安装,非常费劲,而且因为国内外差异,就是我这样的秃头程序员也难以应对。 所以,我们改…

学会RabbitMQ的延迟队列,提高消息处理效率

系列文章目录 手把手教你&#xff0c;本地RabbitMQ服务搭建&#xff08;windows&#xff09; 消息队列选型——为什么选择RabbitMQ RabbitMQ灵活运用&#xff0c;怎么理解五种消息模型 RabbitMQ 能保证消息可靠性吗 推或拉&#xff1f; RabbitMQ 消费模式该如何选择 死信是什么…