四、2023.9.30.C++面向对象end.4

文章目录

  • 49、 简述一下什么是常函数,有什么作用?
  • 50、 说说什么是虚继承,解决什么问题,如何实现?
  • 51、简述一下虚函数和纯虚函数,以及实现原理?
  • 52、说说纯虚函数能实例化吗,为什么?派生类要实现吗,为什么?
  • 53、说说C++中虚函数与纯虚函数的区别?
  • 54、说说 C++ 中什么是菱形继承问题,如何解决?
  • 55、请问构造函数中的能不能调用虚方法?
  • 56、请问拷贝构造函数的参数是什么传递方式,为什么?
  • 57、如何理解抽象类?
  • 58、什么是多态?除了虚函数,还有什么方式能实现多态?
  • 59、简述一下虚析构函数,什么作用?
  • 60、说说什么是虚基类,可否被实例化?
  • 61、简述一下拷贝赋值和移动赋值?
  • 62、仿函数了解吗?有什么作用?
  • 62、C++ 中哪些函数不能被声明为虚函数?

49、 简述一下什么是常函数,有什么作用?

类的成员函数后面加 const,表明这个函数不会对这个类对象的数据成员(准确地说是非静态数据成员)作任何改变
在设计类的时候,一个原则就是对于不改变数据成员的成员函数都要在后面加const,而对于改变数据成员的成员函数不能加 const。所以 const 关键字对成员函数的行为作了更明确的限定:有 const 修饰的成员函数(指 const 放在函数参数表的后面,而不是在函数前面或者参数表内),只能读取数据成员,不能改变数据成员
没有 const 修饰的成员函数,对数据成员则是可读可写的。除此之外,在类的成员函数后面加 const 还有什么好处呢?那就是常量(即 const)对象可以调用 const成员函数,而不能调用非const修饰的函数。正如非const类型的数据可以给const类型的变量赋值一样,反之则不成立。

#include<iostream>
using namespace std;
class CStu {
public:int a;CStu() {a = 12;
}
void Show() const {
//a = 13; //常函数不能修改数据成员cout <<a << "I am show()" << endl;}
};
int main() {CStu st;st.Show();system("pause");return 0;
}

50、 说说什么是虚继承,解决什么问题,如何实现?

虚继承是解决C++多重继承问题的一种手段,从不同途径继承来的同一基类,会在子类中存在多份拷贝。这将存在两个问题:

  • 其一,浪费存储空间;
  • 第二,存在二义性问题,通常可以将派生类对象的地址赋值给基类对象,实现的具体方式是,将基类指针指向继承类(继承类有基类的拷贝)中的基类对象的地址,但是多重继承可能存在一个基类的多份拷贝,这就出现了二义性。虚继承可以解决多种继承前面提到的两个问题。

51、简述一下虚函数和纯虚函数,以及实现原理?

(一)虚函数

  1. C++中的虚函数的作用主要是实现了多态的机制。
  2. 关于多态,简而言之就是用父类型的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数。这种技术可以让父类的指针有“多种形态”,这是一种泛型技术。
  3. 如果调用非虚函数,则无论实际对象是什么类型,都执行基类类型所定义的函数。非虚函数总是在编译时根据调用该函数的对象,引用或指针的类型而确定。如果调用虚函数,则直到运行时才能确定调用哪个函数,运行的虚函数是引用所绑定或指针所指向的对象所属类型定义的版本。虚函数必须是基类的非静态成员函数。
  4. 虚函数的作用是实现动态联编,也就是在程序的运行阶段动态地选择合适的成员函数,在定义了虚函数后,可以在基类的派生类中对虚函数重新定义,在派生类中重新定义的函数应与虚函数具有相同的形参个数和形参类型。以实现统一的接口,不同定义过程。如果在派生类中没有对虚函数重新定义,则它继承其基类的虚函数。
    在这里插入图片描述
class Person{
public://虚函数virtual void GetName(){cout<<"PersonName:xiaosi"<<endl;};
};
class Student:public Person{
public:void GetName(){cout<<"StudentName:xiaosi"<<endl;};
};
int main(){
//指针Person *person = new Student();
//基类调用子类的函数person->GetName();//StudentName:xiaosi
}

虚函数(Virtual Function)是通过一张虚函数表(Virtual Table)来实现的。简称为V-Table。在
这个表中,主是要一个类的虚函数的地址表,这张表解决了继承、覆盖的问题,保证其容真实反应实际的函数。这样,在有虚函数的类的实例中这个表被分配在了这个实例的内存中,所以,当我们用父类的指针来操作一个子类的时候,这张虚函数表就显得由为重要了,它就像一个地图一样,指明了实际所应该调用的函数。

(二)纯虚函数
纯虚函数是在基类中声明的虚函数,它在基类中没有定义,但要求任何派生类都要定义自己的实现的实现方法。
在基类中实现纯虚函数的方法是在函数原型后加“=0” virtualvoid GetName() =0。在很多情
况下,基类本身生成对象是不合情理的。例如,动物作为一个基类可以派生出老虎、孔雀等子类,但动物本身生成对象明显不合常理。为了解决上述问题,将函数定义为纯虚函数,则编译器要求在派生类中必须予以重写以实现多态性。
同时含有纯虚拟函数的类称为抽象类,它不能生成对象。这样就很好地解决了上述两个问题。将函数定义为纯虚函数能够说明,该函数为后代类型提供了可以覆盖的接口,但是这个类中的函数绝不会调用。
声明了纯虚函数的类是一个抽象类。

所以,用户不能创建类的实例,只能创建它的派生类的实例。必须在继承类中重新声明函数(不要后面的=0)否则该派生类也不能实例化,而且它们在抽象类中往往没有定义。定义纯虚函数的目的在于,使派生类仅仅只是继承函数的接口。纯虚函数的意义,让所有的类对象(主要是派生类对象)都可以执行纯虚函数的动作,但类无法为纯虚函数提供一个合理的缺省实现。所以类纯虚函数的声明就是在告诉子类的设计者,“你必须提供一个纯虚函数的实现,但我不知道你会怎样实现它”。

//抽象类
class Person{
public://纯虚函数virtual void GetName()=0;
};
class Student:public Person{
public:Student(){
};
void GetName(){cout<<"StudentName:xiaosi"<<endl;};
};
int main(){Student student;
}

52、说说纯虚函数能实例化吗,为什么?派生类要实现吗,为什么?

  1. 纯虚函数不可以实例化,但是可以用其派生类实例化,示例如下:
class Base
{
public:
virtual void func() = 0;
};
#include<iostream>
using namespace std;
class Base {
public:virtual void func() = 0;
};
class Derived :public Base
{
public:void func() override {cout << "哈哈" << endl;
}
};
int main() {Base *b = new Derived();b->func();return 0;
}
  1. 虚函数的原理采用 vtable。类中含有纯虚函数时,其vtable 不完全,有个空位。
    即“纯虚函数在类的vftable表中对应的表项被赋值为0。也就是指向一个不存在的函数。由于编译器绝对不允许有调用一个不存在的函数的可能,所以该类不能生成对象。在它的派生类中,除非重写此函数,否则也不能生成对象。”所以纯虚函数不能实例化。
  2. 纯虚函数是在基类中声明的虚函数,它要求任何派生类都要定义自己的实现方法,以实现多态性。
  3. 定义纯虚函数是为了实现一个接口,用来规范派生类的行为,也即规范继承这个类的程序员必须实现这个函数。派生类仅仅只是继承函数的接口。纯虚函数的意义在于,让所有的类对象(主要是派生类对象)都可以执行纯虚函数的动作,但基类无法为纯虚函数提供一个合理的缺省实现。所以类纯虚函数的声明就是在告诉子类的设计者,“你必须提供一个纯虚函数的实现,但我不知道你会怎样实现它”。

53、说说C++中虚函数与纯虚函数的区别?

  1. 虚函数和纯虚函数可以定义在同一个类中,含有纯虚函数的类被称为抽象类,而只含有虚函数的类不能被称为抽象类
  2. 虚函数可以被直接使用,也可以被子类重载以后,以多态的形式调用,而纯虚函数必须在子类中实现该函数才可以使用,因为纯虚函数在基类有声明而没有定义。
  3. 虚函数和纯虚函数都可以在子类中被重载,以多态的形式被调用。
  4. 虚函数和纯虚函数通常存在于抽象基类之中,被继承的子类重载,目的是提供一个统一的接口
  5. 虚函数的定义形式: virtual{} ;纯虚函数的定义形式: virtual { } = 0 ;在虚函数和纯虚函数
    的定义中不能有static标识符,原因很简单,被static修饰的函数在编译时要求前期绑定,然而虚函数却是动态绑定,而且被两者修饰的函数生命周期也不一样。

54、说说 C++ 中什么是菱形继承问题,如何解决?

导致问题:菱形继承会导致数据重复和产生歧义;
解决办法:使用虚继承,可确保每份数据自继承一次;

55、请问构造函数中的能不能调用虚方法?

  • 不要在构造函数中调用虚方法,从语法上讲,调用完全没有问题,但是从效果上看,往往不能达到需要的目的。
  • 派生类对象构造期间进入基类的构造函数时,对象类型变成了基类类型,而不是派生类类型。
  • 同样,进入基类析构函数时,对象也是基类类型。
    所以,虚函数始终仅仅调用基类的虚函数(如果是基类调用虚函数),不能达到多态的效果,所以放在构造函数中是没有意义的,而且往往不能达到本来想要的效果。

56、请问拷贝构造函数的参数是什么传递方式,为什么?

  1. 拷贝构造函数的参数必须使用引用传递
  2. 如果拷贝构造函数中的参数不是一个引用,即形如CClass(const CClass c_class),那么就相当于采用了传值的方式(pass-by-value),而传值的方式会调用该类的拷贝构造函数,从而造成无穷递归地调用拷贝构造函数。因此拷贝构造函数的参数必须是一个引用。需要澄清的是,传指针其实也是传值,如果上面的拷贝构造函数写成CClass(const CClass*c_class),也是不行的。事实上,只有传引用不是传值外,其他所有的传递方式都是传值。

57、如何理解抽象类?

  1. 抽象类的定义如下:
    纯虚函数是在基类中声明的虚函数,它在基类中没有定义,但要求任何派生类都要定义自己的实现方法。在基类中实现纯虚函数的方法是在函数原型后加“=0”,有虚函数的类就叫做抽象类。
  2. 抽象类有如下几个特点:
    1)抽象类只能用作其他类的基类,不能建立抽象类对象。
    2)抽象类不能用作参数类型、函数返回类型或显式转换的类型。
    3)可以定义指向抽象类的指针和引用,此指针可以指向它的派生类,进而实现多态性。

58、什么是多态?除了虚函数,还有什么方式能实现多态?

  1. 多态是面向对象的重要特性之一,它是一种行为的封装,就是不同对象对同一行为会有不同的状态。(举例 : 学生和成人都去买票时,学生会打折,成人不会)
  2. 多态是以封装和继承为基础的。在C++中多态分为静态多态(早绑定)和动态多态(晚绑定)两种,其中动态多态是通过虚函数实现,静态多态通过函数重载实现,代码如下:

59、简述一下虚析构函数,什么作用?

  1. 虚析构函数,是将基类的析构函数声明为virtual,举例如下:
class TimeKeeper {public:TimeKeeper() {}virtual ~TimeKeeper() {}
};
  1. 虚析构函数的主要作用是防止内存泄露。

定义一个基类的指针p,在delete p时,如果基类的析构函数是虚函数,这时只会看p所赋值的对
象,如果p赋值的对象是派生类的对象,就会调用派生类的析构函数(毫无疑问,在这之前也会先
调用基类的构造函数,在调用派生类的构造函数,然后调用派生类的析构函数,基类的析构函数,所谓先构造的后释放)
;如果p赋值的对象是基类的对象,就会调用基类的析构函数,这样就不会造成内存泄露。
如果基类的析构函数不是虚函数,在delete p时,调用析构函数时,只会看指针的数据类型,而不会去看赋值的对象,这样就会造成内存泄露。

60、说说什么是虚基类,可否被实例化?

  1. 在被继承的类前面加上virtual关键字,这时被继承的类称为虚基类,代码如下:
class A
class B1:public virtual A;
class B2:public virtual A;
class D:public B1,public B2;
  1. 虚继承的类可以被实例化,举例如下:

61、简述一下拷贝赋值和移动赋值?

  1. 拷贝赋值是通过拷贝构造函数来赋值,在创建对象时,使用同一类中之前创建的对象来初始化新创
    建的对象。
  2. 移动赋值是通过移动构造函数来赋值,二者的主要区别在于
    1)拷贝构造函数的形参是一个左值引用,而移动构造函数的形参是一个右值引用;
    2)拷贝构造函数完成的是整个对象或变量的拷贝,而移动构造函数是生成一个指针指向源对象或
    变量的地址,接管源对象的内存,相对于大量数据的拷贝节省时间和内存空间。

62、仿函数了解吗?有什么作用?

  1. 仿函数(functor)又称为函数对象(function object)是一个能行使函数功能的类。仿函数的语
    法几乎和我们普通的函数调用一样,不过作为仿函数的类,都必须重载operator()运算符,举个例
    子:
class Func{
public:void operator() (const string& str) const {cout<<str<<endl;}
};Func myFunc;myFunc("helloworld!");
>>>helloworld!

62、C++ 中哪些函数不能被声明为虚函数?

常见的不不能声明为虚函数的有:普通函数(非成员函数),静态成员函数,内联成员函数,构造函数,友元函数。

谁懂啊…
虚函数 虚析构函数 虚表指针 虚基类 纯虚函数 虚函数表 虚构造函数 虚继承 虚继承的类
你们虚氏家族太狠了

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

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

相关文章

龙迅LT9611UXC 2PORT MIPICSI/DSI转HDMI(2.0)转换器+音频,内置MCU

龙迅LT9611UXC 1.描述&#xff1a; LT9611UXC是一个高性能的MIPI DSI/CSI到HDMI2.0转换器。MIPI DSI/CSI输入具有可配置的单 端口或双端口&#xff0c;1高速时钟通道和1~4高速数据通道&#xff0c;最大2Gbps/通道&#xff0c;可支持高达16Gbps的总带 宽。LT9611UXC支持突发…

后端基础php

虚拟机安装网络方面名词介绍快速自建web环境&#xff08;phpstudy&#xff09;前端基础mysql语法前端【展示】----后端【功能实现】标准php 【ASP / ASPX / PHP / JSP】0基础 --->php入门编程--->代码 对逻辑要求高变量--->会改变的量 php---->$aHello…

视频监控/视频汇聚/安防视频监控平台EasyCVR配置集群后有一台显示离线是什么原因?

开源EasyDarwin视频监控TSINGSEE青犀视频平台EasyCVR能在复杂的网络环境中&#xff0c;将分散的各类视频资源进行统一汇聚、整合、集中管理&#xff0c;在视频监控播放上&#xff0c;TSINGSEE青犀视频安防监控汇聚平台可支持1、4、9、16个画面窗口播放&#xff0c;可同时播放多…

C#(CSharp)入门教程

目录 C#的第一个程序 变量 折叠代码 变量类型和声明变量 获取变量类型所占内存空间&#xff08;sizeof&#xff09; 常量 转义字符 隐式转换 显示转换 异常捕获 运算符 算术运算符 布尔逻辑运算符 关系运算符 位运算符 其他运算符 字符串拼接 …

Spring实例化源码解析之ComponentScanAnnotationParser(四)

上一章我们分析了ConfigurationClassParser&#xff0c;配置类的解析源码分析。在ComponentScans和ComponentScan注解修饰的候选配置类的解析过程中&#xff0c;我们需要深入的了解一下ComponentScanAnnotationParser的parse执行流程&#xff0c;SpringBoot启动类为什么这么写&…

MySQL体系结构和四层架构介绍

MySQL体系结构图如下&#xff1a; 四层介绍 1. 连接层&#xff1a; 它的主要功能是处理客户端与MySQL服务器之间的连接(比如Java应用程序通过JDBC连接MySQL)。当客户端应用程序连接到MySQL服务器时&#xff0c;连接层对用户进行身份验证、建立安全连接并管理会话状态。它还处理…

企业级磁盘阵列存储系统由硬到软全析

企业级磁盘阵列是由一组设备构成的存储系统,主要包括两种类型的设备,分别是控制器和扩展柜,其中控制器只有一台,扩展柜可以没有,也可以有多台。在EMC的Unity中分别称为DPE(Disk Processor Enclosure)和DAE(Disk Array Enclosure),在华为的OceanStor里面称为控制框和硬…

k8s搭建EFK日志系统

搭建 EFK 日志系统 前面大家介绍了 Kubernetes 集群中的几种日志收集方案&#xff0c;Kubernetes 中比较流行的日志收集解决方案是 Elasticsearch、Fluentd 和 Kibana&#xff08;EFK&#xff09;技术栈&#xff0c;也是官方现在比较推荐的一种方案。 Elasticsearch 是一个实…

chrome插件-入门

chrome插件的作用 1、屏蔽网页上的广告&#xff0c;提高浏览速度和减少视觉干扰 2、捕捉和编辑网页截图 3、改善在社交媒体平台上的体验&#xff0c;例如提供额外的功能&#xff0c;或自定义外观和布局 4、网页翻译 5、保存和组织网页书签和笔记 6、管理日程安排&#xff0c;设…

Python 笔记06(Mysql数据库)

一 基础 1.1 安装 MySQL下载参考&#xff1a;MySQL8.0安装配置教程【超级详细图解】-CSDN博客 测试是否安装并正确配置环境变量&#xff1a; 1.2 查看服务器是否正常运行 1.3 显示数据库 show databases; 1.4 退出 exit 1.5 python 连接 1.6 查主机IP ipconfig

【RabbitMQ实战】07 3分钟部署一个RabbitMQ集群

一、集群的安装部署 我们还是利用docker来安装RabbitMQ集群。3分钟安装一个集群&#xff0c;开始。 前提条件&#xff0c;docker安装了docker-compose。如果没安装的话&#xff0c;参考这里 docker-compose文件参考bitnami官网&#xff1a;https://github.com/bitnami/contai…

一道签到题目 签到.zip

一道签到题目 https://www.xuenixiang.com/ctfexercise-competition-589.html 下载附件&#xff1a;签到.zip双击打开zip包。 进行base64转换 在线 Unicode 编码转换 | 菜鸟工具 (runoob.com) 获得压缩包密码&#xff1a;haishi 文字倒序工具,在线文字倒序 (qqxiuzi.cn)

vue下载在前端存放的pdf文件

vue下载在前端存放的pdf文件 注意&#xff0c;这里要在public文件夹中新建文件夹存放静态资源&#xff0c;不能在src文件夹中新建文件夹存放静态资源&#xff0c;因为public文件夹中的文件资源不会被npm run build打包编译。大家打包一下&#xff0c;就会发现 模板.pdf文件 是存…

C语言进阶---动态内存管理

动态内存管理 前言&#xff1a;一、为什么存在动态内存分配&#xff1f;二、动态内存函数的介绍1.数据在不同区域的储存&#xff1a;2、malloc和free3、calloc4、realloc 三、常见的动态内存错误1、对NULL指针的解引用操作2、对动态开辟空间的越界访问3、对非动态内存开辟的空间…

ASUS华硕ZenBook 13灵耀U 2代U3300F笔记本UX333FN/FA原装出厂Win10系统工厂安装模式

系统自带所有驱动、出厂主题壁纸、系统属性华硕专属LOGO标志、Office办公软件、MyASUS华硕电脑管家等预装程序 下载链接&#xff1a;https://pan.baidu.com/s/1dK0vMZMECPlT63Rb6-jeFg?pwdbym5 所需要工具&#xff1a;16G或以上的U盘(非必需) 文件格式&#xff1a;HDI,SWP,O…

CDH 6.3.2升级Flink到1.17.1版本

CDH&#xff1a;6.3.2 原来的Flink&#xff1a;1.12 要升级的Flink&#xff1a;1.17.1 操作系统&#xff1a;CentOS Linux 7 一、Flink1.17编译 build.sh文件&#xff1a; #!/bin/bash set -x set -e set -vFLINK_URLsed /^FLINK_URL/!d;s/.*// flink-parcel.properties FLI…

R | R及Rstudio安装、运行环境变量及RStudio配置

R | R及Rstudio安装、运行环境变量及RStudio配置 一、介绍1.1 R介绍1.2 RStudio介绍 二、R安装2.1 演示电脑系统2.2 R下载2.3 R安装2.4 R语言运行环境设置&#xff08;环境变量&#xff09;2.4.1 目的2.4.2 R-CMD测试2.4.3 设置环境变量 2.5 R安装测试 三、RStudio安装3.1 RStu…

vue 实现弹出菜单,解决鼠标点击其他区域的检测问题

弹出菜单应该具有的功能&#xff0c;当鼠标点击其他区域时&#xff0c;则关闭该菜单。 问题来了&#xff0c;怎么检测鼠标点击了其他区域而不是当前菜单&#xff1f; 百度“JS检测区域外的点击事件”&#xff0c;会发现有很多方法&#xff0c;有递归检测父元素&#xff0c;有遍…

【JavaEE初阶】 计算机是如何工作的

文章目录 &#x1f332;计算机发展史&#x1f38b;冯诺依曼体系&#xff08;Von Neumann Architecture&#xff09;&#x1f38d;CPU 基本工作流程&#x1f4cc;逻辑门&#x1f388;电子开关 —— 机械继电器(Mechanical Relay)&#x1f388;门电路(Gate Circuit)NOT GATE&…

【强化学习】基础概念

1. Agent (智能体) 智能体是进行决策和学习的实体&#xff0c;它能感知环境的状态&#xff0c;并基于策略采取动作以影响环境。智能体的目标是通过与环境的交互获得最大化的累积奖励。 2. Environment (环境) 环境是智能体所处的外部系统&#xff0c;它与智能体交互。环境的…