【C++】多态面试题

news2024/11/28 3:33:11

在这里插入图片描述

🚀write in front🚀
📜所属专栏: C++学习
🛰️博客主页:睿睿的博客主页
🛰️代码仓库:🎉VS2022_C语言仓库
🎡您的点赞、关注、收藏、评论,是对我最大的激励和支持!!!
关注我,关注我,关注我你们将会看到更多的优质内容!!

在这里插入图片描述

文章目录

  • 前言
  • 面试题:
  • 一.概念查考
  • 二. 问答题
  • 总结

前言

面试题:

我们来看看一道biantai的面试题:
在这里插入图片描述

一.概念查考

  1. 下面哪种面向对象的方法可以让你变得富有(A)
    A: 继承 B: 封装 C: 多态 D: 抽象
  2. (D)是面向对象程序设计语言中的一种机制。这种机制实现了方法的定义与具体的对象无关,而对方法的调用则可以关联于具体的对象。
    A: 继承
    B: 模板
    C: 对象的自身引用
    D: 动态绑定
    这里的动态绑定就是多态
  3. 面向对象设计中的继承和组合,下面说法错误的是?(C)
    A:继承允许我们覆盖重写父类的实现细节,父类的实现对于子类是可见的,是一种静态复用,也称为白盒复用
    B:组合的对象不需要关心各自的实现细节,之间的关系是在运行时候才确定的,是一种动态复用,也称为黑盒复用
    C:优先使用继承,而不是组合,是面向对象设计的第二原则
    D:继承可以使子类能自动继承父类的接口,但在设计模式中认为这是一种破坏了父类的封装性的表现
    事实上组合用的多。
  4. 以下关于纯虚函数的说法,正确的是(A)
    A:声明纯虚函数的类不能实例化对象
    B:声明纯虚函数的类是虚基类
    C:子类必须实现基类的纯虚函数
    D:纯虚函数必须是空函数
    虚基类是菱形继承里面的知识,别搞混
  5. 关于虚函数的描述正确的是(B)
    A:派生类的虚函数与基类的虚函数具有不同的参数个数和类型
    B:内联函数不能是虚函数
    C:派生类必须重新定义基类的虚函数
    D:虚函数可以是一个static型的函数
    下面有解析
  6. 关于虚表说法正确的是(D)
    A:一个类只能有一张虚表
    B:基类中有虚函数,如果子类中没有重写基类的虚函数,此时子类与基类共用同一张虚表
    C:虚表是在运行期间动态生成的
    D:一个类的不同对象共享该类的虚表
    B选项应该是如果我加了一个虚函数,虚表指针就会变化。
  7. 假设A类中有虚函数,B继承自A,B重写A中的虚函数,也没有定义任何虚函数,则(D)
    A:A类对象的前4个字节存储虚表地址,B类对象前4个字节不是虚表地址
    B:A类对象和B类对象前4个字节存储的都是虚基表的地址
    C:A类对象和B类对象前4个字节存储的虚表地址相同
    D:A类和B类虚表中虚函数个数相同,但A类和B类使用的不是同一张虚表
  8. 下面程序输出结果是什么? (A)
#include<iostream>
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. 多继承中指针偏移问题?下面说法正确的是( C )
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
10. 以下程序输出结果是什么()

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;
}
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;
}
class A
{
public:
virtual void func(int val = 1){ std::cout<<"A->"<< val <<std::endl;}

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

  继承的时候,成员函数都在代码段里面。在这里我们通过B的指针调用A类的test()函数,由之前类与对象的知识,每一个成员函数都隐藏了this指针,而A类的this指针类型是A*this,这个时候调用test()其实就是A*this=p,就是多态的构成。然后在通过this->func(),我们就会调用到B的func()函数,这个时候按常理来说就应该选D了,但是答案是B???

  其实啊,虚函数的重写重写的是实现,之前的三同里面的参数相同也只是只的是类型相同,与值无关。所以在多态调用时,我们这里B的func,函数的头用的是A的头,函数的实现用的是B的实现,所以这里就会产生这样的问题。其实虚函数的重写重写的是实现!

当然上面的问题是多态导致的,如果是普通的函数调用,不符合多态,就不会出现函数头和实现分开的现象:

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; }
	void test() { func(); }
};
int main(int argc, char* argv[])
{
	B* p = new B;
	p->test();
	return 0;
}

在这里的结果就是B->0,因为不是多态。

其实我是觉得,多态调用的时候在要通过虚表指针找函数等一系列操作可能就会让其头和实现分离,而普通调用却可以直接找到虚函数的地址,确实挺神奇的。

二. 问答题

  1. 什么是多态?
    答:多态就是不同的对象去做同一件事情产生了不同的结果。

  2. 什么是重载、重写(覆盖)、重定义(隐藏)?
    答:
    重载是同名函数,在参数不同的情况下写出的不同功能的函数
    重写是指派生类中有一个跟基类完全相同的虚函数(三同),对这个函数进行重写
    重定义/隐藏是指在继承时,子类写了一个和父类同名的函数,子类在调用这个同名函数的时候,就会将父类的函数直接隐藏。(只要是继承+函数名相同,直接就是重定义隐藏)

  3. 多态的实现原理?
    答:两个条件:
    必须通过基类的指针或者引用调用虚函数
    被调用的函数必须是虚函数,且派生类必须对基类的虚函数进行重写

  4. inline函数可以是虚函数吗?
    答:可以,不过编译器就忽略inline属性,这个函数就不再是inline,因为虚函数要放到虚表中去

  5. 静态成员可以是虚函数吗?
    答:不能,因为静态成员函数没有this指针,使用类型::成员函数的调用方式无法访问虚函数表,虚函数是用于实现运行时多态性的概念,它需要针对对象的实际类型来确定调用哪个函数版本。静态成员函数不属于对象,而是属于类本身,它们在编译时就已经确定了调用关系,不涉及对象的多态性,因此不适用于虚函数的概念。

  6. 构造函数可以是虚函数吗?
    答:不能,因为对象中的虚函数表指针是在构造函数初始化列表阶段才初始化的。如果把构造函数搞成虚函数,就没办法找到虚函数表指针了。

  7. 析构函数可以是虚函数吗?什么场景下析构函数是虚函数?
    答:可以,并且最好把基类的析构函数定义成虚函数。

  8. 对象访问普通函数快还是虚函数更快?
    答:首先如果是普通调用,是一样快的。如果是指针对象或者是引用对象,则调用的普通函数快,因为构成多态,运行时调用虚函数需要到虚函数表中去查找。

  9. 虚函数表是在什么阶段生成的,存在哪的?
    答:虚函数表是在编译阶段就生成的,一般情况下存在代码段(常量区)的。

  10. C++菱形继承的问题?虚继承的原理?
    答:注意这里不要把虚函数表和虚基表搞混了。

  11. 什么是抽象类?抽象类的作用?
    答:包含纯虚函数的类叫做抽象类(也叫接口类),抽象类不能实例化出对象。派生类继承后也不能实例化出对象,只有重写纯虚函数,派生类才能实例化出对象。纯虚函数规范了派生类必须重写,另外纯虚函数更体现出了接口继承。

总结

  多态的知识还是非常多呢,大家下去一定要多多复习呀!

  更新不易,辛苦各位小伙伴们动动小手,👍三连走一走💕💕 ~ ~ ~ 你们真的对我很重要!最后,本文仍有许多不足之处,欢迎各位认真读完文章的小伙伴们随时私信交流、批评指正!

专栏订阅:
每日一题
C语言学习
算法
智力题
初阶数据结构
Linux学习
C++学习
更新不易,辛苦各位小伙伴们动动小手,👍三连走一走💕💕 ~ ~ ~ 你们真的对我很重要!最后,本文仍有许多不足之处,欢迎各位认真读完文章的小伙伴们随时私信交流、批评指正!

在这里插入图片描述

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

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

相关文章

【AIGC核心技术剖析】研究报告分享与汇总

AIGC研究报告 AI画画工具项目参考 AIGC&#xff08;Artificial General Intelligence Control&#xff09;技术是一种人工智能&#xff08;AI&#xff09;技术&#xff0c;旨在管理和控制人工智能系统的行为&#xff0c;以确保它们在执行任务时遵守一定的规则、伦理和价值观。A…

c进阶--指针进阶

&#x1f33c;&#x1f33c;&#x1f33c;&#x1f33c;&#x1f33c;&#x1f33c;&#x1f33c;&#x1f33c;&#x1f33c;&#x1f33c;&#x1f33c;&#x1f33c;&#x1f33c;&#x1f33c;&#x1f33c; 指针的简单回顾&#x1f33c;&#x1f33c;&#x1f33c;&#x…

助企上云新举措!移动云网盘服务平台正式上线

近日&#xff0c;移动云网盘服务平台&#xff08;DSP&#xff09;V1.0重磅发布。DSP作为移动云首个自研aPaaS平台&#xff0c;具备多存储节点纳管、高效文件管理、极速文件传输、多媒体数据处理、一体化运维支撑等功能特性&#xff0c;可满足文档管理、内容协作、云上会议、数据…

9.30消息队列

发送方&#xff1a; #include<myhead.h>//消息结构体 typedef struct {long msgtype; //消息类型char data[1024]; //消息正文 }Msg_ds;#define SIZE sizeof(Msg_ds)-sizeof(long) //正文大小int main(int argc, const char *argv[]) {//1.创建key值key_t key;if(…

国庆9.30

消息队列实现进程间通信 snd #include <myhead.h> //消息结构体 typedef struct {long msgtype; //消息类型char data[1024]; //消息正文 }Msg_ds;#define SIZE sizeof(Msg_ds)-sizeof(long) //正文大小int main(int argc, const char *argv[]) {//1、创建key…

中国1km分辨率逐月降水数据集(1901-2020)

佳节 中国逐月降水量数据集&#xff08;1901-2021&#xff09;是根据CRU发布的全球0.5气候数据集以及WorldClim发布的全球高分辨率气候数据集&#xff0c;通过Delta空间降尺度方案在中国地区降尺度生成的。使用了496个独立气象观测点数据进行验证&#xff0c;验证结果可信。数…

模块化CSS

1、什么是模块化CSS 模块化CSS是一种将CSS样式表的规则和样式定义封装到模块或组件级别的方法&#xff0c;以便于更好地管理、维护和组织样式代码。这种方法通过将样式与特定的HTML元素或组件相关联&#xff0c;提供了一种更具可维护性、可复用性和隔离性的方式来处理样式。简单…

在MyBatisPlus中添加分页插件

开发过程中&#xff0c;数据量大的时候&#xff0c;查询效率会有所下降&#xff0c;这时&#xff0c;我们往往会使用分页。 具体操作入下&#xff1a; 1、添加分页插件&#xff1a; package com.zhang.config;import com.baomidou.mybatisplus.extension.plugins.Pagination…

整理mongodb文档:副本集二

个人博客 整理mongodb文档:副本集二 个人博客&#xff0c;求推荐&#xff0c;本片内容较为乱 文章概叙 本文章主要讲在MongoDB的副本集中的一些注意点&#xff0c;主要是如何对seconadry进行数据操作&#xff0c;以及对更新数据的一些介绍 查看当前节点 上一集讲了关于搭…

【JavaEE】CSS

CSS 文章目录 CSS语法引入方式内部样式表行内样式表外部样式 选择器基础选择器标签选择器类选择器id选择器通配符选择器 复合选择器后代选择器伪类选择器链接伪类选择器 字体设置设置文本颜色粗细样式文本对齐 背景背景颜色背景平铺背景尺寸 圆角矩形元素显示模式块级元素 盒模…

【Linux】进程控制基础知识

目录 一&#xff0c;fack回顾 二&#xff0c;进程终止 1.进程终止&#xff0c;操作系统做了什么&#xff1f; 2.进程终止&#xff0c;常见的方式 1.main函数的&#xff0c;return 返回码 2. exit()函数 三&#xff0c;进程等待 1. 回收进程方法 &#xff08;1. wait…

cola 架构简单记录

cola 是来自张建飞&#xff08;Frank&#xff09;的偏实现的技术架构&#xff0c;里面的业务身份和扩展点也被MEAF引用&#xff0c;cola本身由java 实现、但其实可以是一种企业通用的技术架构。 业务身份来源 https://blog.csdn.net/significantfrank/article/details/8578556…

Jasypt 实现自定义加解密

如下文章已经讲解了&#xff0c; Jasypt 是什么&#xff0c;怎么集成 Jasypt&#xff0c;怎么使用 Jasypt。 Jasypt 开源加密库使用教程_jasyptstringencryptor-CSDN博客Jasypt 加密框架概述1、Jasypt Spring Boot 为 spring boot 应用程序中的属性源提供加密支持&#xff0c;…

Linux开发工具之文本编译器vim

●IDE例子 Linux编辑器-vim使用 vi/vim的区别简单点来说&#xff0c;它们都是多模式编辑器&#xff0c;不同的是vim是vi的升级版本&#xff0c;它不仅兼容vi的所有指令&#xff0c;而且还有一些新的特性在里面。例如语法加亮&#xff0c;可视化操作不仅可以在终端运行&#xff…

Windows电脑显示部分功能被组织控制

目录 问题描述 解决方法 总结 问题描述 如果你的电脑出现以上情况&#xff0c;建议你使用我这种方法&#xff08;万不得已&#xff09; 解决方法 原因就是因为当时你的电脑在激活的时候是选择了组织性激活的&#xff0c;所以才会不管怎么搞&#xff0c;都无法摆脱组织的控…

发布以太坊测试网络中的第一笔交易

1.安装以太坊钱包 要想发送发布以太坊测试网络中的第一笔交易&#xff0c;首先需要创建一个管理账户的钱包&#xff0c;这个钱包可以理解为管理私钥的容器&#xff0c;具体按照步骤为&#xff1a;打开Chrome浏览器应用商店搜索MetaMask&#xff0c;选择对应的钱包添加至Chrome…

提升API文档编写效率,Dash for Mac是你的不二之选

在编写和开发API文档的过程中&#xff0c;你是否经常遇到查找困难、管理混乱、效率低下等问题&#xff1f;这些都是让人头疼的问题&#xff0c;但现在有了Dash for Mac&#xff0c;一切都将变得简单而高效。 Dash for Mac是一款专为API文档编写和管理设计的工具&#xff0c;它…

SpringBoot 中使用JPA

最近忙里偷闲&#xff0c;想写一点关于JPA的东西&#xff0c;另外也加深下对JPA的理解&#xff0c;才有了此篇博文。 一、JPA JPA &#xff08;Java Persistence API&#xff09;Java持久化API&#xff0c;是一套Sun公司Java官方制定的ORM 规范&#xff08;sun公司并没有实现…

【Java】对象内存图多个对象同一内存地址

目录 学生类 单个对象内存图 多个对象指向同一个内存地址 学生类 Student.java如下&#xff1a; package com.面向对象;public class Student {String name;int age;public void work() {System.out.println("开始敲代码...");} }StudentDemo.java如下&#xff…

MAC地址震荡,STP震荡,OSPF路由协议震荡

目录 一.MAC地址震荡 原因 二层环路 三层环路 避免三层环路的方法 1.最小化路由汇总 2.null0路由 二.STP震荡 原因 三.路由协议震荡 OSPF路由协议震荡 BGP路由震荡 一.MAC地址震荡 原因 MAC地址表震荡也称为MAC地址漂移&#xff0c;是由网络环路造成的&#xff1…