零碎的c++二

虚函数

虚函数是C++中实现多态的一种机制,它允许通过基类指针或引用来调用派生类的成员函数。虚函数的作用是实现动态绑定,即在运行时根据对象的实际类型来确定调用哪个函数。虚函数的声明方式是在函数前加上关键字virtual,如:

class Base {
public:virtual void func(); // 声明一个虚函数
};

虚函数可以有以下几种场景用到:

  • 当我们需要定义一个通用的基类,为不同的派生类提供一个统一的接口时,可以使用虚函数。例如,我们可以定义一个Animal类,为所有动物提供一个虚函数makeSound(),然后让不同的派生类如Dog、Cat等重写这个虚函数,实现各自的叫声。这样,我们就可以通过一个Animal指针或引用来调用任何动物的makeSound()函数,而不需要知道它们的具体类型。
  • 当我们需要利用多态特性来实现一些设计模式时,可以使用虚函数。例如,我们可以使用虚函数来实现模板方法模式,这是一种行为型设计模式,它定义了一个算法的骨架,并将一些步骤延迟到子类中实现。这样,我们可以通过改变子类来改变算法的某些部分,而不影响算法的结构。例如,我们可以定义一个Sorter类,为所有排序算法提供一个虚函数sort(),然后让不同的派生类如BubbleSorter、QuickSorter等重写这个虚函数,实现各自的排序方法。这样,我们就可以通过一个Sorter指针或引用来调用任何排序算法的sort()函数,而不需要知道它们的具体类型。
  • 当我们需要在析构函数中释放一些资源时,可以使用虚函数。如果我们有一个基类指针或引用指向一个派生类对象,并且想要通过它来删除这个对象时,如果基类的析构函数不是虚函数,那么只会调用基类的析构函数,而不会调用派生类的析构函数,这可能导致资源泄漏或内存错误。为了避免这种情况,我们应该将基类的析构函数声明为虚函数,这样就会先调用派生类的析构函数,然后再调用基类的析构函数,从而正确地释放资源。

虚函数和纯虚函数的区别

  • 虚函数是在基类中声明并定义的函数,它在函数前加上关键字virtual,如:
class Base {
public:virtual void func(); // 声明一个虚函数
};

虚函数可以在派生类中被override,也就是用不同的实现来替换基类的实现。如果派生类没有override虚函数,那么就会继承基类的实现。虚函数的作用是实现动态绑定,即在运行时根据对象的实际类型来确定调用哪个函数。例如,我们可以定义一个Shape类,为所有图形提供一个虚函数area(),然后让不同的派生类如Circle、Rectangle等override这个虚函数,实现各自的面积计算方法。这样,我们就可以通过一个Shape指针或引用来调用任何图形的area()函数,而不需要知道它们的具体类型。

  • 纯虚函数是在基类中声明但不定义的函数,它在函数后加上=0,如:
class Base {
public:virtual void func() = 0; // 声明一个纯虚函数
};

纯虚函数没有默认的实现,它要求任何派生类都必须提供自己的实现方法。如果派生类没有提供纯虚函数的实现,那么这个派生类也不能被实例化。纯虚函数的作用是定义一个接口,规范派生类的行为。例如,我们可以定义一个Animal类,为所有动物提供一个纯虚函数makeSound(),然后要求所有派生类如Dog、Cat等必须实现这个纯虚函数,提供各自的叫声方法。这样,我们就可以通过一个Animal指针或引用来调用任何动物的makeSound()函数,而不需要知道它们的具体类型。

  • 虚函数和纯虚函数的区别主要有以下几点:

    • 虚函数可以有默认的实现,纯虚函数没有默认的实现。
    • 虚函数可以被派生类继承或override,纯虚函数必须被派生类override。
    • 虚函数可以通过基类指针或引用调用基类或派生类的实现,纯虚函数只能通过基类指针或引用调用派生类的实现。
    • 包含虚函数的类可以被实例化,包含纯虚函数的类不能被实例化,称为抽象类。
  • 虚函数和纯虚函数的使用场景主要有以下几种:

    • 当我们需要定义一个通用的基类,为不同的派生类提供一个统一的接口时,可以使用虚函数。例如,我们可以定义一个Shape类,为所有图形提供一个虚函数area()。
    • 当我们需要利用多态特性来实现一些设计模式时,可以使用虚函数。例如,我们可以使用虚函数来实现模板方法模式,这是一种行为型设计模式,它定义了一个算法的骨架,并将一些步骤延迟到子类中实现。
    • 当我们需要在析构函数中释放一些资源时,应该使用虚析构函数。如果我们有一个基类指针或引用指向一个派生类对象,并且想要通过它来删除这个对象时,如果基类的析构函数不是虚析构函数,那么只会调用基类的析构函数,而不会调用派生类的析构函数,这可能导致资源泄漏或内存错误。为了避免这种情况,我们应该将基类的析构函数声明为虚析构函数,这样就会先调用派生类的析构函数,然后再调用基类的析构函数,从而正确地释放资源。
    • 当我们需要定义一个抽象的基类,规范派生类的行为,但不提供默认的实现时,可以使用纯虚函数。例如,我们可以定义一个Animal类,为所有动物提供一个纯虚函数makeSound()。

深拷贝和浅拷贝

C++中的深拷贝和浅拷贝是指在对象复制时,对于类中的资源(如动态内存、文件句柄等)的处理方式。具体来说:

  • 浅拷贝是指只复制对象的基本类型成员变量和指针类型成员变量的值,而不复制指针所指向的资源。这样,原对象和新对象会共享同一块资源,如果其中一个对象修改或释放了资源,会影响另一个对象的状态。浅拷贝是编译器默认提供的拷贝行为,一般适用于类中没有资源或不需要管理资源的情况。
  • 深拷贝是指除了复制对象的基本类型成员变量和指针类型成员变量的值外,还会为指针所指向的资源重新分配内存,并复制资源内容。这样,原对象和新对象会拥有各自独立的资源,互不影响。深拷贝需要程序员显式地定义拷贝构造函数和赋值运算符重载函数,以实现自定义的拷贝行为。深拷贝一般适用于类中有资源并需要管理资源的情况。

下面是一个简单的例子来说明深拷贝和浅拷贝的区别:

#include <iostream>
using namespace std;class Person {
public:// 有参构造函数Person(int age, int height) {m_age = age;m_height = new int(height); // 动态分配内存}// 拷贝构造函数Person(const Person& p) {m_age = p.m_age;// m_height = p.m_height; // 浅拷贝m_height = new int(*p.m_height); // 深拷贝}// 析构函数~Person() {if (m_height != NULL) {delete m_height; // 释放内存m_height = NULL;}}// 打印信息void show() {cout << "age: " << m_age << ", height: " << *m_height << endl;}
private:int m_age; // 年龄int* m_height; // 身高
};int main() {Person p1(18, 180); // 创建一个Person对象p1.show(); // 打印信息Person p2(p1); // 用p1初始化p2,调用拷贝构造函数p2.show(); // 打印信息*p2.m_height = 190; // 修改p2的身高p2.show(); // 打印信息p1.show(); // 打印信息return 0;
}

如果使用浅拷贝,那么输出结果为:

age: 18, height: 180
age: 18, height: 180
age: 18, height: 190
age: 18, height: 190

可以看到,修改p2的身高也影响了p1的身高,这是因为p1和p2共享了同一块内存。另外,在析构函数中释放内存时,也会出现重复释放或野指针的问题。

如果使用深拷贝,那么输出结果为:

age: 18, height: 180
age: 18, height: 180
age: 18, height: 190
age: 18, height: 180

可以看到,修改p2的身高不影响p1的身高,这是因为p1和p2各自拥有了独立的内存。另外,在析构函数中释放内存时,也不会出现问题。

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

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

相关文章

Json“牵手”亚马逊商品详情数据方法,亚马逊商品详情API接口,亚马逊API申请指南

亚马逊平台是美国最大的一家网络电子商务公司&#xff0c;亚马逊公司是1995年成立&#xff0c;刚开始只做网上书籍售卖业务&#xff0c;后来扩展到了其他产品。现在已经是全世界商品品种最多的网上零售商和第二互联网公司&#xff0c;亚马逊是北美洲、欧洲等地区的主流购物平台…

数据结构:线性表之-循环双向链表(万字详解)

目录 基本概念 1&#xff0c;什么是双向链表 2&#xff0c;与单向链表的区别 双向链表详解 功能展示&#xff1a; 1. 定义链表 2&#xff0c;创建双向链表 3&#xff0c;初始化链表 4,尾插 5&#xff0c;头插 6&#xff0c;尾删 判断链表是否被删空 尾删代码 7&a…

我们这一代人的机会是什么?

大家好&#xff0c;我是苍何&#xff0c;今天作为专业嘉宾参观了 2023 年中国国际智能产业博览会&#xff08;智博会&#xff09;&#xff0c;是一场以「智汇八方&#xff0c;博采众长」为主题的汇聚全球智能技术和产业创新的盛会&#xff0c;感触颇深&#xff0c;随着中国商业…

JVM相关知识点

Java可以跨平台的原因 Java可以跨平台的原因是因为它使用了Java虚拟机&#xff08;JVM&#xff09;作为中间层。Java源代码首先被编译成字节码&#xff0c;然后由JVM解释执行或即时编译成本地机器代码。这样&#xff0c;在不同的操作系统上&#xff0c;只需要安装适合该操作系…

9月11日作业

思维导图 代码 #include <iostream> #include<string.h>using namespace std;class myString { private:char *str; //记录c风格的字符串int size; //记录字符串的实际长度 public://无参构造myString():size(10){str new char[size]; …

从零学算法2849

2849.给你四个整数 sx、sy、fx、fy 以及一个 非负整数 t 。 在一个无限的二维网格中&#xff0c;你从单元格 (sx, sy) 开始出发。每一秒&#xff0c;你 必须 移动到任一与之前所处单元格相邻的单元格中。 如果你能在 恰好 t 秒 后到达单元格 (fx, fy) &#xff0c;返回 true &a…

目标检测YOLO实战应用案例100讲-毫米波辐射图像去模糊重建与目标检测(续)

目录 3.3基于RSRN模型的毫米波辐射图像去模糊重建方法 3.3.2非线性映射 3.3.3多尺度模糊提取

淘宝京东扣库存怎么实现的

1. 使用kv存储实时的库存&#xff0c;直接在kv里扣减&#xff0c;避免用分布式锁 2. 不要先查再扣&#xff0c;直接扣扣扣&#xff0c;扣到负数&#xff0c;&#xff08;增改就直接在kv里做&#xff09;&#xff0c;就说明超卖了&#xff0c;回滚刚才的扣减 3. 同时写MQ&…

vue中打印指定dom元素

和window.print()效果一样&#xff0c;调出打印窗口&#xff0c;只是当前使用的插件是vue-print-nb 官网地址&#xff1a;vue-print-nb vue2中使用 安装插件 npm install vue-print-nb --save导入插件 import Print from vue-print-nb // 全局使用 Vue.use(Print);//or// 单…

如何确保ChatGPT的文本生成对特定行业术语的正确使用?

确保ChatGPT在特定行业术语的正确使用是一个重要而复杂的任务。这涉及到许多方面&#xff0c;包括数据预处理、模型训练、微调、评估和监控。下面我将详细介绍如何确保ChatGPT的文本生成对特定行业术语的正确使用&#xff0c;并探讨这一过程中的关键考虑因素。 ### 1. 数据预处…

JVM类加载机制

目录 一、Java为什么是一种跨平台的语言&#xff1f; 二、Java代码的执行流程 解释执行为主&#xff0c;编译执行为辅&#xff1a; 三、类加载的过程 3.1、加载 类加载器&#xff08;就是加载类的&#xff09;分为&#xff1a; 3.1.1、启动类加载器&#xff08;Bootstrap…

UMA 2 - Unity Multipurpose Avatar☀️三.给UMA设置默认服饰Recipes

文章目录 🟥 项目基础配置🟧 给UMA配置默认服饰Recipes🟨 设置服饰Recipes属性🟥 项目基础配置 将 UMA_DCS 预制体放到场景中创建空物体,添加DynamicCharacterAvatar 脚本,选择 HumanMaleDCS作为我们的基本模型配置默认Animator 🟧 给UMA配置默认服饰Recipes 服饰Re…

回归预测 | MATLAB实现PCA-BP主成分降维结合BP神经网络多输入单输出回归预测

回归预测 | MATLAB实现PCA-BP主成分降维结合BP神经网络多输入单输出回归预测 目录 回归预测 | MATLAB实现PCA-BP主成分降维结合BP神经网络多输入单输出回归预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 MATLAB实现PCA-BP主成分降维算法结合BP神经网络多输入单输出回…

Linux命令(78)之read

linux命令之read 1.read介绍 linux命令read用来接收键盘或其它文件的输入&#xff0c;得到输入后&#xff0c;read命令将接收的数据放入到标准变量中。 2.read用法 read [参数] [变量名称] read常用参数 参数说明-p后面跟提示信息-e可以使用命令补全功能-n输入文本的长度-s…

【数据结构】串

串 串的顺序实现简单的模式匹配算法KMP算法KMP算法的进一步优化 串的顺序实现 初始化 #define MaxSize 50 typedef char ElemType;//顺序存储表示 typedef struct{ElemType data[MaxSize];int length; }SString;/*** 初始化串*/ void InitString(SString *string) {for (int …

点云从入门到精通技术详解100篇-基于车载激光点云的道路标线提取及分类方法

目录 前言 车载 LiDAR 技术基础理论 2.1 车载 LiDAR 系统组成 2.2 车载 LiDAR 系统工作原理

Python基础continue和break关键字

continue 和 break 关键字 continue 含义&#xff1a;表示跳过本次循环&#xff0c;继续下次循环 注意&#xff1a;continue在while循环中不可以使用 例子&#xff1a; for i in range(5): if i 3: continue else: print(i) #结果为0,1,2,4 当i 3的时候&#xff0c;跳…

变压器耐压试验电压及电源容量的计算

被试变压器的额定电压为&#xff08;11081. 25%&#xff09; /10. 5kV&#xff0c; 联接组标号为 YNd11。 试验时高压分接开关置于第 1 分接位置&#xff0c; 即高压侧电压为 126kV&#xff0c; 高、 低压电压比 K1126/&#xff08;√310. 5&#xff09; 6. 93。 现以 A 相试验…

Cmake入门(一文读懂)

目录 1、Cmake简介2、安装CMake3、CMakeLists.txt4、单目录简单实例4.1、CMakeLists.txt4.2、构建bulid内部构建外部构建 4.3、运行C语言程序 5、多目录文件简单实例5.1、根目录CMakeLists.txt5.2、源文件目录5.3、utils.h5.4、创建build 6、生成库文件和链接外部库文件7、注意…

Mysql5.7(Docker环境)实现主从复制

文章目录 前言一、MySQL主从数据库同步如何实现&#xff1f;(理论)1.1 为什么要使用数据库主从1.2 数据库主从实现原理是什么&#xff1f; 二、Docker环境配置MySQL5.7主从(实践)2.1 配置安装Master2.2 配置安装Slave 前言 本文章将以MySQL5.7版本来讲诉MySQL主从复制的原理以…