是不是看错了,C++ 构造函数也可以是虚函数?(一)

以下内容为本人的学习笔记,如需要转载,请声明原文链接 微信公众号「ENG八戒」https://mp.weixin.qq.com/s/2HXYlggENXcSwTdydtof0g

首先,C++ 构造函数可以是虚函数吗?

语法上来说,答案是不行的。类对象的创建依赖于类构造函数的执行,在构造函数执行之前虚函数指针还是空的,虚函数指针需要被初始化才能使用,所以构造函数不能为虚函数。笔者之前有篇文章对此也做过相关刨析,有兴趣可关注我然后搜索阅读《刨析一下C++构造析构函数能不能声明为虚函数的背后机理?》。

那么为什么要说 C++ 构造函数也可以是虚函数?

这要回到需求上来分析,假设正在设计一个画板,我们可以在上面添加编辑各种图形,比如方框、三角形、圆形等。

编辑自然包括复制粘贴等操作,复制的时候面对的是对象,由于类的多态特性,对象可能基于派生类实例化,访问是通过基类指针变量,所以不一定会知道当前对象的具体类型。那么如何拷贝对象?

常规拷贝对象

如果我们知道目标对象的类型,那么拷贝对象的常规做法是直接调用类的拷贝构造函数(copy contrutor),看例子

#include <iostream>
using namespace std;class Implementation
{
public:Implementation(){cout << "default constructor" << endl;}Implementation(const Implementation &other){cout << "copy constructor" << endl;}Implementation& operator= (const Implementation &other){cout << "operator=" << endl;return *this;}
};int main()
{Implementation x;Implementation y = x;return 0;
}

欸,不是要演示拷贝构造函数的调用吗,为什么上面的 main 函数里用的是等号 = 表达式?

注意:创建并初始化对象时调用的等号 = 不会调用赋值操作符,虽然类中已实现了赋值操作符,由下面的输出结果来看,实际上是调用了拷贝构造函数。如何区分什么情况下等号 = 表达式才会调用赋值操作符的实现?请记住,拷贝构造函数用于初始化未存在的对象,赋值操作符用于替换已存在的对象的状态,两者区别的关键因素是对象是否已存在。而上面的例子中,由于等号 = 表达式是初始化对象,所以该对象是未存在的,理所当然就是调用了拷贝构造函数。

output:

default constructor
copy constructor

动态克隆

如果我们面对对象时,正如开头的画板中,复制一个已存在的具体图形,但是不能确定其具体类型,又应该如何拷贝这些对象呢?

下面创建一些图形,基础图形特征用基类 BaseShape 表示,各种具体图形用 BaseShape 的派生类表示:

class BaseShape
{// ...
};class Square : public BaseShape
{// ...
};class Rectangle : public BaseShape
{// ...
};int main()
{BaseShape *s1 = new Square();BaseShape *s2 = new Rectangle();// ...return 0;
}

在上面这个例子中,创建具体的图形对象,指针分别存放在基类指针变量 s1 和 s2 中。

在后续的使用中,仅仅依靠基类对象指针,并且不清楚对象的创建类型,于是无法直接使用创建类型对应的拷贝构造函数复制对象。

但是接口仍然能被基类指针调用,是否可以通过对象能直接调用的接口,赋予接口一定的魔法,利用类的多态特性实现动态拷贝?

下面给基类 BaseShape 添加个接口(没有函数体实现的纯虚函数),为了凸显接口的意图—拷贝对象,特意命名为 Clone(),并在派生类中给出实现:

class BaseShape
{
public:// ...virtual BaseShape *Clone() = 0;
};class Square : public BaseShape
{
public:// ...Square *Clone(){return new Square(*this);}
};class Rectangle : public BaseShape
{
public:// ...Rectangle *Clone(){return new Rectangle(*this);}
};

在派生类中的接口被重写时,可以直接调用各自的拷贝构造函数,使得复制对象又变得如此简单了,避免了语法上的限制。

如果你细心的话,会发现派生类对接口 Clone() 重写后返回值的类型与基类的声明不同。基类中返回接口 Clone() 的返回值是指向基类对象的指针,而各个派生类中接口 Clone() 重写后返回值分别是指向派生类对象的指针。这在 c++ 代码中是合法的,被称呼为协差(Covariance)。

所谓协差(Covariance),就是基类虚函数的返回值为指向对象的指针时,派生类重写该虚函数并且返回值同样为指向对象的指针,前后两个返回的指针指向的对象类型可以不同,但是要求后一个类型(派生类)指针可转换为前一个类型(基类)的指针,也就是向上转换(Upcasting)。

从上面的代码可见,接口 Clone() 做的事情和拷贝构造函数一样,都是拷贝对象,但接口 Clone() 属于虚函数,于是,这个接口 Clone() 也被称呼为 虚拷贝构造函数


全文未结束,更多精彩欢迎关注我!

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

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

相关文章

世界人工智能大会 | 江行智能大模型解决方案入选“AI赋能新型工业化创新应用优秀案例”

日前&#xff0c;2024世界人工智能大会暨人工智能全球治理高级别会议在上海启幕。本次大会主题为“以共商促共享&#xff0c;以善治促善智”&#xff0c;汇聚了上千位全球科技、产业界领军人物&#xff0c;共同探讨大模型、数据、新型工业化等人工智能深度发展时代下的热点话题…

[AI 大模型] Anthropic Claude

文章目录 [AI 大模型] Anthropic Claude简介模型架构发展新技术和优势示例 [AI 大模型] Anthropic Claude 简介 Anthropic Claude 是由 Anthropic 开发的一系列大型语言模型&#xff0c;旨在提供高性能、可靠和安全的 AI 解决方案。Claude 模型以其在语言处理、推理、分析和编…

响应式R2DBC数据库mybatis

介绍 响应式&#xff1a;Web、网络、IO&#xff08;存储&#xff09;、中间件&#xff08;Redis、MySQL&#xff09; 应用开发&#xff1a; ● 网络 ● 存储&#xff1a;MySQL、Redis ● Web&#xff1a;Webflux ● 前端&#xff1b; 后端&#xff1a;Controller – Service –…

【C++ STL】模拟实现 vector

标题&#xff1a;【C STL】模拟实现 vector 水墨不写bug &#xff08;图片来源于网络&#xff09; 正文开始&#xff1a; STL中的vector是一个动态数组&#xff0c;支持随机访问&#xff0c;可以根据需要来扩展数组空间。 本项目将实现vector的部分常用功能&#xff0c;以增强…

阿里云 Ubuntu 开启允许 ssh 密码方式登录

以前用的 centos&#xff0c;重置系统为 ubuntu 后在ssh 远程连接时遇到了点问题&#xff1a; 在阿里云控制台重置实例密码后无法使用密码进行 SSH 连接登录 原因&#xff1a;阿里云 Ubuntu 默认禁用密码登录方式 解决办法&#xff1a; 先使用其他用户登录到服务器 这里进来…

国产操作系统安装配置auditd审计工具 _ 统信 _ 麒麟 _ 中科方德

原文链接&#xff1a;国产操作系统安装配置auditd审计工具 | 统信 | 麒麟 | 中科方德 Hello&#xff0c;大家好啊&#xff01;今天给大家带来一篇在国产桌面操作系统上部署auditd审计工具的文章。auditd是Linux审计系统的核心守护进程&#xff0c;用于记录系统安全相关的事件和…

Python自动化测试系列[v1.0.0][自动化测试报告]

BeautifulReport测试报告 获取BeautifulReport模块 BeautifulReport 源码Clone地址为 BeautifulReport &#xff0c;其中BeautifulReport.py和其template是我们需要的 BeautifulReport 如下代码是BeautifulReport.py的源码&#xff0c;其中几个注释的地方需要注意&#xff…

等保测评实战指南:从准备到实施的全面剖析

在数字化时代&#xff0c;信息安全已成为企业发展的基石。信息安全等级保护&#xff08;简称“等保”&#xff09;测评作为评估和提升信息系统安全防护能力的重要手段&#xff0c;越来越受到企业的重视。本文将从实战角度出发&#xff0c;全面剖析等保测评的准备、实施及后续改…

排序算法(算法篇)

算法之排序算法 排序算法 概念&#xff1a; 我们在的排序工作能在主存中完成的&#xff0c;我们就叫这种算法叫做内部排序不能在主存中完成而必须在磁盘或磁带上完成的排序算法叫做外部排序 冒泡排序 概念&#xff1a; 冒泡排序是一个很简单的排序算法&#xff0c;冒泡排…

【python】PyQt5可视化开发,鼠标键盘实现联动界面交互逻辑与应用实战

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

一个简单的 Vue 组件例子

https://andi.cn/page/621509.html

AIGC在软件开发中的崛起:赋能开发者还是重塑职业版图?

在科技日新月异的今天&#xff0c;生成式人工智能&#xff08;AIGC, Artificial Intelligence Generated Content&#xff09;正以前所未有的速度渗透至各行各业&#xff0c;其中&#xff0c;软件开发领域尤为显著。从基础的代码自动补全到复杂的系统架构设计&#xff0c;AIGC技…

ubuntu 删除 ab-* 开头的文件夹及内容

在Ubuntu中&#xff0c;你可以使用rm命令和find命令组合来删除所有以ab-开头的文件夹及其内容。以下是一个命令示例&#xff1a; rm -rf $(find /path/to/start -type d -name ab-*) 请将/path/to/start替换成你想要开始搜索的目录路径。这条命令会递归地删除所有以ab-开头的文…

GEE代码实例教程详解:地表温度与土地覆盖类型分析

简介 在本篇博客中&#xff0c;我们将使用Google Earth Engine (GEE) 对地表温度数据进行分析&#xff0c;并探究不同土地覆盖类型&#xff08;特别是水体和城市区域&#xff09;的地表温度变化。通过MODIS数据集&#xff0c;我们可以监测2001年至2024年间的数据。 背景知识 …

YOLOv10改进 | Conv篇 | 利用DualConv二次创新C2f提出一种轻量化结构(轻量化创新)

一、本文介绍 本文给大家带来的改进机制是利用DualConv改进C2f提出一种轻量化的C2f&#xff0c;DualConv是一种创新的卷积网络结构&#xff0c;旨在构建轻量级的深度神经网络。它通过结合33和11的卷积核处理相同的输入特征映射通道&#xff0c;优化了信息处理和特征提取。Dual…

二叉树的序列化和反序列化(Java)

概述 关于面试中常见的其他二叉树算法题&#xff0c;参考面试算法之二叉树(Java)。二叉树的定义&#xff08;注意到有使用lombok提供的两个注解&#xff09;&#xff1a; lombok.Data lombok.AllArgsConstructor private static class TreeNode {private TreeNode left;priva…

java 参数传递(尤其注意参数是对象的情况)

8大基本数据类型为 值传递 类和数组为 引用传递&#xff0c;传递的是地址 但是要注意虽然类是引用传递&#xff0c;但是要注意&#xff0c;调用方法是新开一个栈 因此如果进行p null或者 Person p new Person()等语句&#xff0c;要格外注意&#xff1a; 如果主函数再次输出…

基于场景的 Java Spring Boot 热门面试问题

随着 Spring Boot 继续主导 Java 生态系统&#xff0c;对熟悉这个强大框架的熟练开发人员的需求正在上升。如果您正在准备 Spring Boot 面试&#xff0c;尤其是作为一名经验丰富的专业人士&#xff0c;那么专注于测试您的实践知识和解决问题能力的基于场景的问题至关重要。本文…

音频demo:将PCM数据与alaw、mulaw、g711数据的相互转换

1、README 前言 (截图来源&#xff1a;https://blog.csdn.net/u014470361/article/details/88837776) 我的理解&#xff1a; 首先需要知道的是u-law/a-law是用于脉冲编码的压缩/解压缩算法。而G.711是指在8KHz采样率&#xff08;单声道&#xff09;中&#xff0c;使用的u-law或…

LLM- 注意力机制

一&#xff1a;什么是注意力机制&#xff0c;以及产生背景&#xff1f; &#xff08;1&#xff09;&#xff1a;RNN模型[RNN模型]的缺点&#xff1a;下图是例如RNN模型解决机器翻译的例子&#xff0c;从这个例子可以看到Encoder最后一个向量&#xff08;eos&#xff09;送给了…