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

news2024/11/27 1:30:23

文章目录

  • 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.coloradmin.cn/o/1053056.html

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

相关文章

Python实验二

1&#xff1a;编程计算 1&#xff5e;100 偶数的和。 要求&#xff1a;输出结果为整数&#xff0c;宽度为 8&#xff0c;居中对齐&#xff0c;空白处填充符号“*”。 提示&#xff1a; range(2,101,2)生成的整数列表从 2 开始到 100 结束&#xff0c;步长为 2&#xff0c;即 …

华为云云耀云服务器L实例评测|云耀云服务器L实例部署Linux管理面板mdserver-web

华为云云耀云服务器L实例评测&#xff5c;云耀云服务器L实例部署Linux管理面板mdserver-webl 一、云耀云服务器L实例介绍1.1 云耀云服务器L实例简介1.2 云耀云服务器L实例特点 二、mdserver-web介绍2.1 mdserver-web简介2.2 mdserver-web特点2.3 主要插件介绍 三、本次实践介绍…

高数:第二章:一元函数微分学

文章目录 一、导数与微分1.导数的概念(1)导数的定义(2)左右导数(3)定理&#xff1a;可导与左右导数的关系(4)可导三要素(5)用导数定义判断可导性 2.微分的概念(1)微分的定义(2)微分与可导的关系 3.导数与微分的几何意义(1)导数 f ′ ( x 0 ) f(x_0) f′(x0​)的几何意义&#x…

【LLM】Windows10环境部署阿里通义千问大模型(Qwen-14B-Chat-Int4)

文章目录 环境文件准备项目代码模型相关文件 运行准备工作运行demo Tips 环境 系统版本&#xff1a;Windows 10 企业版 版本号&#xff1a;20H2 系统类型&#xff1a;64 位操作系统, 基于 x64 的处理器 处理器&#xff1a;Intel Core™ i7-13700K CPU 3.40GHz 机带 RAM&#…

1340. 跳跃游戏 V;2039. 网络空闲的时刻;2767. 将字符串分割为最少的美丽子字符串

1340. 跳跃游戏 V 核心思想&#xff1a;动态规划记忆化搜索。定义dfs(i)&#xff0c;表示从i开始最多可以访问多少个下标&#xff0c;然后统计往左跳和往右边跳的最大值&#xff0c;思路其实比较简单&#xff0c;但是代码我感觉还是不太好想。 2039. 网络空闲的时刻 核心思想…

CH347读写SPI Flash

CH347读写SPI Flash 前面耽搁了几天&#xff0c;今天终于把CH347 SPI接口调试好了。 CH347动态库中SPI接口函数如下&#xff1a; typedef struct _SPI_CONFIG{UCHAR iMode; // 0-3:SPI Mode0/1/2/3UCHAR iClock; // 060…

数据分析方法:RFM模型

一、RFM基本原理 RFM是三个单词的缩写&#xff1a; 最近一次消费时间&#xff08;Recency&#xff09;&#xff0c;取数的时候一般取最近一次消费记录到当前时间的间隔&#xff0c;比如&#xff1a;7天、30天、90天未到店消费&#xff1b;直观上&#xff0c;一个用户太久不到…

Windows 下安装及配置 MySQL 8.1 (图文教程)

目录 下载 MySQL安装 MySQL配置 MySQL修改密码配置环境变量 卸载 MySQL开源项目微服务商城项目前后端分离项目 下载 MySQL 访问 MySQL 下载地址&#xff1a;https://dev.mysql.com/downloads/mysql/ 下载 MySQL 时&#xff0c;你可以选择 ZIP 包或 MSI 安装&#xff1a; ZIP包…

智能合约漏洞,Dyna 事件分析

智能合约漏洞&#xff0c;Dyna 事件分析 1. 漏洞简介 https://twitter.com/BlockSecTeam/status/1628319536117153794 https://twitter.com/BeosinAlert/status/1628301635834486784 2. 相关地址或交易 攻击交易 1&#xff1a; https://bscscan.com/tx/0x7fa89d869fd1b89e…

【Java 进阶篇】MySQL 事务详解

在数据库管理中&#xff0c;事务是一组SQL语句的执行单元&#xff0c;它们被视为一个整体。事务的主要目标是保持数据库的一致性和完整性&#xff0c;即要么所有SQL语句都成功执行&#xff0c;要么所有SQL语句都不执行。在MySQL中&#xff0c;事务起到了非常重要的作用&#xf…

【C++】map、set,multiset和multimap的使用及底层原理【完整版】

目录 一、map和set的使用 1、序列式容器和关联式容器 2、set的使用讲解 3、map的使用讲解 二、multiset和multimap 1、multiset和multimap的使用 2、OJ题&#xff1a;前k个高频单词 一、map和set的使用 1、序列式容器和关联式容器 序列式容器&#xff1a;vector/list/s…

java遇到的问题

java遇到的问题 Tomcat与JDK版本问题 当使用Tomcat10的版本用于springmvc借用浏览器调试时&#xff0c;使用JDK8浏览器会报异常。 需要JDK17&#xff08;可以配置多个JDK环境&#xff0c;切换使用&#xff09;才可以使用&#xff0c;配置为JAVA_HOME路径&#xff0c;否则&a…

Linux系统编程系列之进程间通信-消息队列

一、什么是消息队列 消息队列是system-V三种IPC对象之一&#xff0c;是进程间通信的一种方式。 二、消息队列的特性 允许发送的数据携带类型&#xff08;指定发送给谁&#xff09;&#xff0c;具有相同类型的数据在消息队列内部排队&#xff0c;读取的时候也要指定类型&#x…

STM32三种开发方式及标准库和HAL库的编程差异

三种开发方式 STM32基于标准库函数和HAL库编程差异_stm32库函数和hal库-CSDN博客本文目的是以串口通信来简要分析STM32使用标准库函数和HAL库函数编程的差异。目录&#xff08;一&#xff09;开发方式1.配置寄存器2.库函数3.HAL库&#xff08;二&#xff09;库函数与HAL库对比…

格点数据可视化(美国站点的日降雨数据)

获取美国站点的日降雨量的格点数据&#xff0c;并且可视化 导入模块 from datetime import datetime, timedelta from urllib.request import urlopenimport cartopy.crs as ccrs import cartopy.feature as cfeature import matplotlib.colors as mcolors import matplotli…

3D孪生场景搭建:模型区域摆放

前面介绍完了NSDT场景编辑器的线性绘制和阵列绘制&#xff0c;本章将讲述下编辑器的另一种绘制方式&#xff1a;区域绘制。 1、区域绘制功能简介 在场景中绘制资产时&#xff0c;除使用上述两个的方式外&#xff0c;NSDT 编辑器还支持使用区域绘制的方式进行绘制。先选取需要…

【C/C++笔试练习】——数组名和数组名、switch循环语句、数据在计算机中的存储顺序、字符串中找出连续最长的数字串、数组中出现次数超过一半的数字

文章目录 C/C笔试练习1.数组名和&数组名&#xff08;1&#xff09;数组名和&数组名的差异&#xff08;2&#xff09;理解数组名和指针偏移&#xff08;3&#xff09;理解数组名代表的含义&#xff08;4&#xff09;理解数组名代表的含义 2.switch循环语句&#xff08;6…

FFmpeg 命令:从入门到精通 | ffplay 简单过滤器

FFmpeg 命令&#xff1a;从入门到精通 | ffplay 简单过滤器 FFmpeg 命令&#xff1a;从入门到精通 | ffplay 简单过滤器视频旋转视频反转视频旋转和反转音频变速播放视频变速播放音视频同时变速更多参考 FFmpeg 命令&#xff1a;从入门到精通 | ffplay 简单过滤器 本节介绍了简…

【CFD小工坊】浅水方程的离散及求解方法

【CFD小工坊】浅水方程的离散及求解方法 前言基于有限体积法的方程离散界面通量与源项计算干-湿网格的处理数值离散的稳定性条件参考文献 前言 我们模型的控制方程&#xff0c;即浅水方程组的表达式如下&#xff1a; ∂ U ∂ t ∂ E ( U ) ∂ x ∂ G ( U ) ∂ y S ( U ) U…