C++学习笔记----9、发现继承的技巧(一)---- 使用继承构建类(5)

news2024/10/17 9:36:54

2.5.2、virtual的评判

        在像Java这样的有些语言中,所有的成员函数自动为virtual,所以它们可以被恰当地重载。在c++中不是这样。关于在c++中反对使一切皆为virtual的争论,以及一开始就有了这个关键字的原因,与vtable的开销有关。调用一个virtual成员函数,程序需要执行额外的操作去间接引用指向合适代码的指针去执行。在大部分情况下对性能的影响是微乎其微的,但是c++的设计者认为,至少在当时是这样,让程序员自己去决定其性能影响是必要的,会更好一些。如果成员函数从来不会被重载,就没有必要使其为virtual,去承担性能的损失。然而,在今天的CPU的情况下,性能的影响是以纳秒计的,对于未来的CPU影响会更小。在大部分应用程序中,在使用virtual成员函数与避免使用它们之间测量不出性能的不同。

        但是,在特定的情况下,性能开销可能会比较大,可能需要有可以避免的选项。例如,假设你有一个Point类,该类有一个vitual成员函数。如果有另外一个数据结构保存了上百万甚至上十亿的Point,在第一个point的virtual成员函数的调用会产生巨大的开销。在这种情况下,在Point类中避免任何virtual成员函数就可能是明智的了。

        每个对象对内存的使用也是一个小小的影响。在成员函数实现之外,每个对象也需要一个指向它的vtable的指针,它占用了很小量的空间。在绝大部分情况下这不是一个问题。然而,有时候确实也有问题。再举刚才的那个Point类的例子,容器保存了上十亿的Point。在这种情况下,这额外的内存要求也变得很严重。

2.5.3、virtual析构函数的需要

        析构函数几乎总是virtual。使析构函数non-virtual很容易地导致内存没有被对象析构函数释放掉的情况发生。只有把类标记成final才能使得它的析构函数non-virtual。

        例如,如果一个继承类在构造函数中使用内存动态分配,在析构函数中删除,如果析构函数从来不会被调用的话,它就不会被释放。同样地,如果继承类有在类实例被破坏时自动删除的成员,例如std::unique_ptr,那么如果析构函数不被调用的话,那些成员也不会被删除。

        如下代码所示,如果它是non-virtual的话,是很容易的“糊弄”编译器,让它忽略对析构函数的调用的。

import std;

using namespace std;

class Base
{
public:
	Base() = default;
	~Base() {}
};

class Derived : public Base
{
public:
	Derived()
	{
		m_string = new char[30];
		println("m_string allocated");
	}

	~Derived()
	{
		delete[] m_string;
		println("m_string deallocated");
	}

private:
	char* m_string;
};

int main()
{
	Base* ptr{ new Derived{} };   // m_string is allocated here.
	delete ptr; // ~Base is called, but not ~Derived because the destructor
				// is not virtual!
}

        从下面的输出可以看出来,Derived对象从来没有被调用过,也就是说,“m_string deallocated”信息从来没有输出过:

m_string allocated

        从技术上讲,上面代码中的delete调用的行为没有被标准定义。在这种没有定义的情况下c++编译器可以做它想做的任何事儿。然而,大部分编译器只是调用基类的析构函数,而不是继承类的析构函数。

        修正措施就是在基类中标记析构函数为virtual。如果你不想在析构函数中做额外的工作,只是想使其为virtual,可以显式地缺省它。下面是例子:

class Base
{
public:
	Base() = default;
	virtual ~Base() = default;
};

        这样改了以后,输出就与预想的一致了:

m_string allocated
m_string deallocated

        记住从c++11以后,拷贝构造函数与拷贝赋值操作符的生成如果类有一个用户定义的析构函数的话会失效。基本上,一旦你有了一个用户声明的析构函数,五规则就来了。这意味着你需要声明拷贝构造函数,拷贝赋值操作符,move构造函数,与move赋值操作符,也可以显式地缺省它们。本章的例子中没有这样做,是由于保持准确到位的考虑。

        警告:除非是有特别的原因不去做,或者类被标识为了final,析构函数都应该被标记为virtual。构造函数不可以也没有必要为virtual,因为总是要在生成对象时指定确切的类构建。

        在本章的一开始,建议在成员函数上使用override关键字,意思是重载基类的成员函数。在析构函数上使用override关键字也是可能的。这确保了在基类中的析构函数不是virtual的情况下编译器会触发错误。可以将virtual,override,与default组合在一起,举例如下:

class Derived : public Base
{
public:
    virtual  ̃Derived() override = default;
};

2.6、防止重载

        除了把整个类标记为final,c++也允许将单个的成员函数标记为final。这样的成员函数不能在继承类中被重载。例如,在DerivedDerived中的Derived类中的someFunction()重载会导致编译错误:

class Base
{
public:
    virtual  ̃Base() = default;
    virtual void someFunction();
};

class Derived : public Base
{
public:
    void someFunction() override final;
};

class DerivedDerived : public Derived
{
public:
    void someFunction() override; // Compilation error.
};

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

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

相关文章

猪圈密码简单实例

猪圈密码简单实例 猪圈密码表 根据上面的密码表,得到每个字母所对应的符号如下 例如单词the的加密结果为:

IO编程--单字符、字符串、格式化、模块化实现文件拷贝以及登录注册

一、完成标准io的单字符、字符串、格式化、模块化实现两个文件的拷贝 代码如下&#xff1a; 1.单字符 #include <myhead.h> int main(int argc, const char *argv[]) {//打开文件FILE* fpfopen("test.txt","r"); FILE* fqfopen("copy_test.txt&…

leetcode:744. 寻找比目标字母大的最小字母(python3解法)

难度&#xff1a;简单 给你一个字符数组 letters&#xff0c;该数组按非递减顺序排序&#xff0c;以及一个字符 target。letters 里至少有两个不同的字符。 返回 letters 中大于 target 的最小的字符。如果不存在这样的字符&#xff0c;则返回 letters 的第一个字符。 示例 1&a…

2024国际潜水小姐大赛中国区总决赛盛典在广州举行,吉林选手张潇文获冠军!

传承“以美之名&#xff0c;保护海洋”的精神&#xff0c;2024年10月15日晚&#xff0c;2024国际潜水小姐大赛中国区总决赛盛典在广州渔民新村隆重举行&#xff01;来自全国多个城市&#xff0c;经过层层选拔产生的20位佳丽齐聚广州&#xff0c;以独特的女性水下之美和健康美&a…

初识算法 · 二分查找(1)

目录 前言&#xff1a; 二分查找 题目解析 算法原理 算法编写 搜索插入位置 题目解析 算法原理 算法编写 前言&#xff1a; 本文呢&#xff0c;我们从滑动窗口窗口算法移步到了二分查找算法&#xff0c;我们简单了解一下二分查找算法&#xff0c;二分查找算法是一个十…

安科瑞末端组合式智慧用电装置在高校宿舍中的应用

1相关背景 学校宿舍用电隐患 安全用电历来都是学校安全工作的一个重点&#xff0c;然而每年因此发生的人身伤害以及火灾事故却在继续&#xff0c;究其原因&#xff0c;主观上是我们的防患意识淡薄&#xff0c;客观上则是由于学生在宿舍使用违规电器、乱拉电线造成的。 现代的…

Java IO 基础知识

IO 流简介 IO 即 Input/Output&#xff0c;输入和输出。数据输入到计算机内存的过程即输入&#xff0c;反之输出到外部存储&#xff08;比如数据库&#xff0c;文件&#xff0c;远程主机&#xff09;的过程即输出。数据传输过程类似于水流&#xff0c;因此称为 IO 流。IO 流在…

java关于如何实现读取各种类型的文件核心属性方法,比如获取标题和作者、主题等;附带远程的https的地址文件读取方法;

有两种方法&#xff1a; 通过提供的现成api进行调用读取pdf文件&#xff0c;或doc、xlsx、pptx文件&#xff1b;可能商业需要付费 https://www.e-iceblue.cn/pdf_java_document_operation/set-pdf-document-properties-in-java.html Spire.PDF for Java import com.spire.pdf…

为什么SSH协议是安全的?

SSH的传输层协议&#xff08;Transport Layer Protocol&#xff09;和用户鉴权协议&#xff08;Authentication Protocol&#xff09;确保数据的传输安全&#xff0c;这里只介绍传输层协议&#xff0c;是SSH协议的基础。 本文针对SSH2协议。 1、客户端连接服务器 服务器默认…

基于springboot实习管理系统

作者&#xff1a;计算机学长阿伟 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、ElementUI等&#xff0c;“文末源码”。 系统展示 【2024最新】基于JavaSpringBootVueMySQL的&#xff0c;前后端分离。 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;…

k8s use-context是什么

kubectl 的 use-context 命令用于在 Kubernetes 集群中切换上下文&#xff08;context&#xff09;&#xff0c;从而方便地在多个集群或命名空间之间进行操作。一个上下文定义了 kubectl 使用的 集群、用户 和 命名空间 的组合。 use-context 的作用&#xff1a; 每个上下文&…

msql事务隔离级别 线上问题

1. 对应代码 解决方式&#xff1a; 在事务隔离级别为可重复读&#xff08;RR&#xff09;时&#xff0c;数据库确实通常会记录当前数据的快照。 在可重复读隔离级别下&#xff0c;事务在执行期间看到的数据是事务开始时的数据快照&#xff0c;即使其他事务对数据进行了修改&am…

考研前所学c语言02(2024/10/16)

1.一个十进制的数转化为二进制的就是不断除二取余&#xff0c;得到的余数从下到上取 比如123&#xff1a; 结果为&#xff1a; 同理其他的十进制转八进制&#xff0c;十六进制就除八&#xff0c;除十六即可 再比如123转十六进制&#xff1a; 因为余数是11&#xff0c;十六进…

超详细的finalshell安装数据库以及数据库的基本操作

一、下载 MySQL Enterprise Edition Downloads | Oraclehttps://www.oracle.com/mysql/technologies/mysql-enterprise-edition-downloads.html 这边有不同的版本&#xff0c;要看你的操作系统&#xff08;centos7 / centos8&#xff09;安装的是哪个版本 我把连接提取出来了&…

Vivado - Aurora 8B/10B IP

目录 1. 简介 2. 设计调试 2.1 Physical Layer 2.2 Link Layer 2.3 Receiver 2.4 IP 接口 2.5 调试过程 2.5.1 Block Design 2.5.2 释放 gt_reset 2.5.3 观察数据 3. 实用技巧 3.1 GT 坐标与布局 3.1.1 选择器件并进行RTL分析 3.1.2 进入平面设计 3.1.3 收发器布…

stm32 F4和F7的硬件CRC保持一致的设置

stm32F4系列的CRC没什么设置选项 逆向一下算法&#xff1a;http://www.ip33.com/crc.html 在stm32F7里面&#xff0c;CRC设置很丰富&#xff0c;如下设置可以和f4算出来的保持一致

HCIP——以太网交换安全(四)DHCP Snooping

目录 一、DHCP Snooping的知识点 二、DHCP Snooping实验拓扑 三、总结 一、DHCP Snooping的知识点 1.1、DHCP snooping 概述&#xff1a; ①DHCP Snooping使能DHCP的一种安全特性&#xff0c;用于保证DHCP客户端从合法的DHCP服务端获取IP地址。DHCP服务器记录DHCP客户端IP…

沐风老师3DMAX地形散布插件TerrainScatter使用方法详解

3DMAX地形散布插件TerrainScatter&#xff0c;根据画定的区域范围和地形起伏&#xff0c;一键种植树木、批量摆放建筑等&#xff0c;对于熟练3dmax的用户&#xff0c;也可以使用TerrainScatter插件制作屋顶摆放瓦片的效果。该插件工作方式是将源对象的副本放置到闭合曲线范围内…

香港科技大学广州|可持续能源与环境学域博士招生宣讲会—大连理工大学专场!!!(暨全额奖学金政策)

香港科技大学广州&#xff5c;可持续能源与环境学域博士招生宣讲会—大连理工大学专场&#xff01;&#xff01;&#xff01;&#xff08;暨全额奖学金政策&#xff09; ⏰时间&#xff1a;2024年10月24日&#xff08;星期四&#xff09;16:00 &#x1f3e0;地点&#xff1a;…

【刷题册】2024.10.13 - 2024.10.15

目录 一、2024.10.131.1 BC153 [NOIP2010]数字统计1.2 NC313 两个数组的交集1.2.1 思路一&#xff1a;暴力O(N^2)1.2.2 思路二&#xff1a;hash 1.3 AB5 点击消除 二、2024.10.142.1 BC64⽜⽜的快递2.2 DP4 最⼩花费爬楼梯2.3 数组中两个字符串的最⼩距离 三、2024.10.153.1 BC…