C++学习笔记----9、发现继承的技巧(四)---- 多态继承(3)

news2024/10/23 9:25:16

6、未来考虑

        从面向对象设计的角度,新的SpreadsheetCell层次结构的实现确定是一次提升。然而,对于真实世界的spreadsheet程序来说这样的类层次结构还不够,有如下几个原因。

        首先,除了提升的设计,还缺失一个属性:从一个单元格类型转换为另一个的能力。通过分成两个类,单元格对象变得松散了。为了提供将DoubleSpreadsheetCell转化为StringSpreadsheetCell的能力,还要加一个转换构造函数,也叫做类型构造函数。与拷贝构造函数外观类似,但是它不是同一个类的对象的引用,而是一个同胞类的对象的引用。记住现在要声明一个缺省的构造函数,它可以被显式缺省,因为只要你自己一声明任何构造函数,编译器就不会再生成了。

export class StringSpreadsheetCell : public SpreadsheetCell
{
public:
	StringSpreadsheetCell() = default;

	StringSpreadsheetCell(const DoubleSpreadsheetCell& cell)
		: m_value{ cell.getString() }
	{
	}
    // Remainder omitted for brevity.	
};

        使用转换构造函数,给定一个DoubleSpreadsheetCell,可以容易地生成一个StringSpreadsheetCell。然而,不要给这些转换指针或引用搞晕。将一个同胞指针或引用从一个转换为另一个是不灵的,除非你重载了转换操作符。

        警告:层次结构上,总是可以向上转换,有时可以向下转换。通过改变cast操作符或使用reinterpret_cast()在层次结构之间转换是可能的,但都不推荐。

        其次,怎么实现单元格的重载的操作符是一个有趣的总是,有几种可能的方法。

        一种方法是实现单元格的每一种组合的操作符的一个版本。对于只有两个继承类,是可管理的。会有一个operator+函数来加两个double单元格,来加两个string单元格 ,以及来加一个double到一个string单元格 。对于每一种组合,要决定结果是什么。例如,两个double单元格相加的结果可以是两个值的算术相加。两个string单元格的相加结果可以是两个string联结的string,等等。

        另一个方法是决定通用表示。早期的实现已经在string上作为各种通用的表示标准化。单独的operator+可以通过利用通用表示囊括所有情况。

        另外一种方法是一个混合。operator+可以提供来添加两个DoubleSpreadsheetCell结果放在DoubleSpreadsheetCell。该操作符可以在double_spreadsheet_cell模块中实现,如下:

export DoubleSpreadsheetCell operator+(const DoubleSpreadsheetCell& lhs,
	const DoubleSpreadsheetCell& rhs)
{
	DoubleSpreadsheetCell newCell;
	newCell.set(lhs.getValue() + rhs.getValue());
	return newCell;
}

        该操作符可以测试如下:

		DoubleSpreadsheetCell doubleCell;
		doubleCell.set(8.4);
		DoubleSpreadsheetCell result{ doubleCell + doubleCell };
		println("{}", result.getString());  // Prints 16.800000

        当两个操作数中至少一个是StringSpreadsheetCell时提供第二个operator+。可以决定该操作符的结果应该总是一个string单元格。可以给string_spreadsheet_cell模块添加一个这样的操作符,可以实现如下:

export StringSpreadsheetCell operator+(const StringSpreadsheetCell& lhs,
	const StringSpreadsheetCell& rhs)
{
	StringSpreadsheetCell newCell;
	newCell.set(lhs.getString() + rhs.getString());
	return newCell;
}

        只要编译器有方法将特殊的单元格转换为StringSpreadsheetCell,操作符就管用。拿前面例子中使用DoubleSpreadsheetCell作参数的StringSpreadsheetCell构造函数,如果这是让operator+唯一工作的方式的话,编译器会自动执行转换。这意味着下面的代码将一个double单元格到一个string单元格是可以的,即使只提供了两个operator+的实现:一个是两个double单元格相加,一个是两个string单元格相加。

		DoubleSpreadsheetCell doubleCell;
		doubleCell.set(8.4);
		StringSpreadsheetCell stringCell;
		stringCell.set("Hello ");
		StringSpreadsheetCell result{ stringCell + doubleCell };
		println("{}", result.getString());  // Prints Hello 8.400000

        如果对多态还有一点儿不确信,以此例代码开始搞明白它。实验代码练习多态的多个方面是一个伟大的起点。

7、为干净的virtual成员函数提供实现

        从技术上来讲,为干净的virtual成员函数提供实现是可能的。该实现不能在类定义本身,必须在外部提供。虽然类保持抽象,任何继承类仍然要求提供干净的virtual成员函数的实现。由于类保持抽象,不能生成实例。干净的virtual成员函数的实现仍然可以被调用,例如,从继承类,下面的代码段展示了这一点:

class Base
{
public:
    virtual void doSomething() = 0; // Pure virtual member function.
};

// An out-­of-­class implementation of a pure virtual member function.
void Base::doSomething() { println("Base::doSomething()"); }

class Derived : public Base
{
public:
    void doSomething() override
    {
        // Call pure virtual member function implementation from base class.
        Base::doSomething();
        println("Derived::doSomething()");
    }
};

int main()
{
    Derived derived;
    Base& base { derived };
    base.doSomething();
}

        输出如预期:

Base::doSomething()
Derived::doSomething()

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

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

相关文章

利用 Direct3D 绘制几何体—7.编译着色器

在 Direct3D 中,着色器程序必须先被编译为一种可移植的字节码。接下来,图形驱动程序将获取这些字节码,并将其重新编译为针对当前系统 GPU 所优化的本地指令 [ATI1]。我们可以在运行期间用下列函数对着色器进行编译。 HRESULT D3DCompileFrom…

创建型模式-----(单例模式)

目录 基本概念 饿汉式: 懒汉式: 上锁双判空版本 std::call_once版本: C11标准后局部静态变量版本: 项目中单例模板的应用 基本概念 单例模式:在程序运行期间只有一份,与程序生存周期一样,…

对比学习论文随笔 1:正负样本对(Contrastive Learning 基础论文篇)

为了阅读的流畅,当前针对相同的代理任务按时间顺序进行梳理,涉及仅使用正负样本思想且优化目标一致的「基础」论文(2018-2020),编码器均采用 ResNet。 文章目录 前言对比学习和代理任务(Pretext task&#…

浪潮云启操作系统(InLinux)bcache缓存实践:理解OpenStack环境下虚拟机卷、Ceph OSD、bcache设备之间的映射关系

前言 在OpenStack平台上,采用bcache加速ceph分布式存储的方案被广泛用于企业和云环境。一方面,Ceph作为分布式存储系统,与虚拟机存储卷紧密结合,可以提供高可用和高性能的存储服务。另一方面,bcache作为混合存储方案&…

Java笔试06

在Java中,异常可以分为两大类:编译时异常(编译时检查异常)和运行时异常(非编译时检查异常)。 编译时异常(Checked Exceptions)是指在编译时期必须被捕获或声明抛出的异常。这些异常…

字节流写入文件

一、创建输出流对象表示的文件三种方式 方法一: FileOutputStream fos new FileOutputStream("fos.txt",true);//最简便方法二: FileOutputStream fos new FileOutputStream(new File("fos.txt"));方法三; File f ne…

Python | Leetcode Python题解之第502题IPO

题目: 题解: class Solution:def findMaximizedCapital(self, k: int, w: int, profits: List[int], capital: List[int]) -> int:if w > max(capital):return w sum(nlargest(k, profits))n len(profits)curr 0arr [(capital[i], profits[i]…

HTML作业

作业 复现下面的图片 复现结果 代码 <!DOCTYPE html> <html><head><meta charset"utf-8"><title></title></head><body><form action"#"method"get"enctype"text/plain"><…

Java程序设计:spring boot(7)——数据访问操作

目录 1 查询操作 1.1 接口方法定义 1.2 映射文件配置 1.3 UserService 1.4 UserController 2 添加操作 2.1 接口方式定义 2.2 映射文件配置 2.3 添加 commons-lang3 依赖 2.4 AssertUtil ⼯具类 2.5 ParamsException ⾃定义异常 2.6 UserService 2.7 ResultInfo …

UDP传输协议Linux C语言实战

文章目录 1.UDP简介1.1特点1.2 UDP协议头部格式1.2.1 **UDP头部**&#xff1a;1.2.2 **头部意义**&#xff1a;1.2.3 **头部参数**&#xff1a; 1.3 UDP数据长度控制1.4 UDP协议建立框架 2. 函数介绍2.1 sendto函数2.2 recvform函数2.3 其他函数 3.实例3.1 通用结构体、IPV4结构…

算法的学习笔记—(牛客JZ50)

&#x1f600;前言 在处理字符串时&#xff0c;寻找第一个只出现一次的字符是一项常见的任务。本文将探讨几种有效的解法&#xff0c;包括使用 HashMap 和位集&#xff08;BitSet&#xff09;。 &#x1f3e0;个人主页&#xff1a;尘觉主页 文章目录 &#x1f970;第一个只出现…

软件分享丨豆包电脑端 AI 助手

豆包电脑端 AI 助手是由字节跳动推出&#xff0c;旨在为用户提供高效便捷的工作和学习体验。它能在工作、学习等场景中发挥重要作用&#xff0c;为用户提供智能辅助&#xff0c;下面简单介绍它的特点&#xff1a; 高效搜索&#xff1a;像优化后的百度&#xff0c;直接提问就能…

【本科毕业设计】基于单片机的智能家居防火防盗报警系统

基于单片机的智能家居防火防盗报警系统 相关资料链接下载摘要Abstract第1章 绪论1.1课题的背景1.2 研究的目的和意义 第2章 系统总体方案设计2.1 设计要求2.2 方案选择和论证2.2.1 单片机的选择2.2.2 显示方案的选择 第3章 系统硬件设计3.1 整体方案设计3.1.1 系统概述3.1.2 系…

C#通过异或(^)运算符制作二进制加密(C#实现加密)

快速了解异或运算符&#xff1a; 异或运算符在C#中用 “^” 来表示 口诀&#xff1a;相同取0&#xff0c;相异取1 简单加密解密winform示例&#xff1a; /// <summary>/// 异或运算符加密实现/// </summary>/// <param name"p_int_Num">初始值<…

生成式 AI 与向量搜索如何扩大零售运营:巨大潜力尚待挖掘

在竞争日益激烈的零售领域&#xff0c;行业领导者始终在探索革新客户体验和优化运营的新途径&#xff0c;而生成式 AI 和向量搜索在这方面将大有可为。从个性化营销到高效库存管理&#xff0c;二者在零售领域的诸多应用场景中都展现出变革性潜力&#xff0c;已成为保持行业领先…

云电脑的真实使用体验

最近这几年&#xff0c;关于云电脑的宣传越来越多。 小枣君之前曾经给大家介绍过云电脑&#xff08;链接&#xff09;。简单来说&#xff0c;它属于云计算的一个应用。通过在云端虚拟出一些虚拟电脑&#xff0c;然后让用户可以远程使用&#xff08;仍然需要借助本地电脑&#x…

使用爬虫爬取Python中文开发者社区基础教程的数据

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;开发者-曼亿点 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 曼亿点 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a…

CANoe_C#调用CDD和CAPL调用CDD方法对比

引言 在汽车电子系统的开发和测试中,CANoe作为一款强大的网络仿真工具,广泛应用于各种通信协议的模拟和验证。为了实现复杂的测试场景,开发者可以使用不同的编程语言和方法来调用CANoe的功能。其中,C#和CAPL(CANoe Programming Language)是两种常用的编程方式。本文将对…

Golang | Leetcode Golang题解之第498题对角线遍历

题目&#xff1a; 题解&#xff1a; func findDiagonalOrder(mat [][]int) []int {m, n : len(mat), len(mat[0])ans : make([]int, 0, m*n)for i : 0; i < mn-1; i {if i%2 1 {x : max(i-n1, 0)y : min(i, n-1)for x < m && y > 0 {ans append(ans, mat[x…

学习笔记——交换——STP(生成树)工作原理

三、工作原理 STP的基本原理是在一个有二层环路的网络中&#xff0c;交换机通过运行STP&#xff0c;自动生成一个没有环路的网络拓扑。这个无环网络拓扑也叫做STP树(STP Tree)&#xff0c;树节点为某些交换机&#xff0c;树枝为某些链路。当网络拓扑发生变化时&#xff0c;STP…