Effective C++学习笔记(7)

news2024/12/23 16:10:29

目录

  • 条款41:了解隐式接口和编译多态
  • 条款42:了解typename的双重意义
  • 条款43:学习处理模板化基类内的名称
  • 条款44:将与参数无关的代码抽离templates
  • 条款45:运用成员函数模板接受所有兼容类型
  • 条款46:需要类型转换时请为模板定义非成员函数
  • 条款47:请使用traits classes表现类型信息
  • 条款48:认识模板元编程

条款41:了解隐式接口和编译多态

  • 显示接口:在源码中可以找到明确可见的函数接口。
    在这里插入图片描述

- 隐式接口:不是基于函数签名式,而是有效表达式组成的接口。如下图,函数接口最终实例化成什么函数和模板参数T有关,在代码编译之前是不确定的。
在这里插入图片描述

  • 运行期多态:在运行期虚函数指针根据指向对象确定哪一个虚函数该被绑定调用。
  • 编译期多态:在编译期以不同的模板参数具现化会导致调用不同的函数。
  • 对classes而言接口是显式的(explicit),以函数签名为中心。多态则是通过 virtual函数发生于运行期
  • 对template参数而言,接口是隐式的(implicit),奠基于有效表达式。多态则是通过template具现化和函数重载解析(function overloading resolution)发生于编译期

条款42:了解typename的双重意义

  • 当声明template类型参数时,class和typename意义完全相同。建议使用typename
  • template内出现的名称如果相依于某个template参数,称之为从属名称(dependent names)。如果从属名称在 class内呈嵌套状,我们称它为嵌套从属名称(nested dependent name)。
  • 当嵌套从属名称表示一个类型时,需要加上typename前缀,表示是一个类型,也叫做嵌套从属类型名称;如果不加typename前缀,默认这个嵌套从属名称是一个非类型(例如某个类的静态成员变量C::value)。
    在这里插入图片描述
    在这里插入图片描述
  • “typename必须作为嵌套从属类型名称的前缀词”这一规则的例外是,**typename不可以出现在base classes list内的嵌套从属类型名称之前,也不可在member initialization list(成员初值列)中作为base class修饰符。**例如:
    在这里插入图片描述
  • 对于冗长的嵌套从属类型名称可用typedef简化
    在这里插入图片描述

条款43:学习处理模板化基类内的名称

  • C++拒绝这个调用的原因:它知道base class templates有可能被特化,而那个特化版本可能不提供和一般性 template相同的接口。因此它往往拒绝在 templatized base classes(模板化基类,本例的MsgSender)内寻找继承而来的名称(本例的 sendClear)。实例化前编译器不进入base class作用域内查找。就某种意义而言,当我们从Object Oriented C++跨进Template C++,继承就不像以前那般畅行无阻了。
    在这里插入图片描述

  • 解决方法统一思路:对编译器承诺“base class template的任何特化版本都将支持其一般(泛化)版本所提供的接口”。

  • 解决方法1:在base class 函数调用动作之前加上“this->”
    在这里插入图片描述

  • 解决方法2:使用using声明式提前声明模板基类函数
    在这里插入图片描述

  • 解决方法3(不推荐):明确指出调用的函数位于模板基类里。若调用的是virtual函数,这种明确修饰会关闭“virtual绑定行为”(只会调用基类的虚函数,而不会调用继承类中对应重写的虚函数):
    在这里插入图片描述

  • 编译器的诊断时间可能发生在早期(当解析derived class template 的定义式时),也可能发生在晚期(当那些templates被特定之template 实参具现化时)。C++的政策是宁愿较早诊断,这就是为什么“当base classes 从templates中被具现化时”
    它假设它对那些baseclasses的内容毫无所悉的缘故。

条款44:将与参数无关的代码抽离templates

  • 模板代码膨胀:其二进制码带着重复(或几乎重复)的代码、数据,或两者。其结果有可能源码看起来合身而整齐,但目标码(object code) 却不是那么回事。
  • Templates生成多个classes和多个函数,所以任何template代码都不该与某个造成膨胀的template参数产生相依关系。
  • 非类型模板参数(non- type template parameters) 而造成的代码膨胀,往往可消除,做法是以函数参数或class成员变量替换template参数
  • 类型参数(type parameters)而造成的代码膨胀,往往可降低,做法是让带有完全相同二进制表述( binary representations)的具现类型( instantiation types)共享实现码
  • 有时愈是尝试精密的做法,事情变得愈是复杂。从某个角度看,一点点代码重复反倒看起来有点幸运了。需要在具体不同平台进行衡量。

条款45:运用成员函数模板接受所有兼容类型

  • 以智能指针是“行为像指针”的对象,讨论如何实现成员函数模板用于接受所有兼容类型,泛化智能指针操作类似指针操作。
  • 通过成员函数模板建立一个泛化的copy构造函数,使得该拷贝构造函数可以支持智能指针隐式转换。这个行为只有当“存在某个隐式转换可将-一个U指针转为-一个T指针”时才能通过编译,而那正是我们想要的。这个构造函数只在其所获得的实参隶属适当(兼容)类型时才通过编译:
    在这里插入图片描述
  • 通过成员函数模板建立一个泛化的赋值操作“=”函数。下图所有构造函数都是explicit, 惟有“泛化copy构造函数”除外。那意味从某个shared_ ptr 类型隐式转换至另一个shared ptr 类型是被允许的,但从某个内置指针或从其他智能指针类型进行隐式转换则不被认可(如果是显式转换如cast强制转型动作倒是可以)。
    在这里插入图片描述
  • member templates 并不改变语言规则,而语言规则说,如果程序需要一个copy构造函数,你却没有声明它,编译器会为你暗自生成一个。 在class内声明泛化copy构造函数(是个member template)并不会阻止编译器生成它们自己的copy构造函数(一个non-template),所以如果你想要控制copy构造的方方面面,你必须同时声明泛化copy构造函数和“正常的”copy构造函数。相同规则也适用于赋值( assignment)操作
    在这里插入图片描述

条款46:需要类型转换时请为模板定义非成员函数

  • 模板中,根据实参推导模板参数类型时不支持隐式类型转换推导。如果一个模板类中,模板内的函数需要参数类型转换,成员函数无法做到。函数参数隐式类型转换之前需要确定该函数存在,而实例化之前成员函数并不存在。
  • 可在模板类内中采用friend函数声明和定义,使其声明跟随模板类一起实例化,之后再调用的时候就可以自动找到该函数的声明,进行隐式类型转换(下图中可在*重载中输入int类型数据,使其隐式调用Rational的int类型构造函数,隐式转换为Rational<int>)。
    在这里插入图片描述
  • 由于定义于class内中的函数暗自成为inline,可采用class内中friend函数啥也不干,只调用一个外部辅助函数即可,减小inline声明所带来的冲击
    在这里插入图片描述

条款47:请使用traits classes表现类型信息

  • STL中迭代器可分为五类,继承关系如下图:
    (1). Input 迭代器,只能一步一步向前移动,只能读取内容,且仅读取一次。
    (2). Output 迭代器,只能一步一步向前移动,只能写入内容,且仅写入一次。
    (3). Forward 迭代器,只能一步一步向前移动,可读可写多次。
    (4). Bidirectianol 迭代器,只能一步一步向前或向后移动,可读可写多次。
    (5). Random Access 迭代器,可以在常量时间以任意步数向前或向后移动,可读可写多次。

在这里插入图片描述

  • Traits是一种技术,也是一个C++程序员共同遵守的协议。它对内置类型和用户自定义类型的表现必须一样好

  • Traits设计实现流程(例子是实现advance模板函数,可以接受各种类型的迭代器进行移动):
    -(1)确认若干你希望将来可取得的类型信息;
    -(2)为该信息选一个名称;
    在这里插入图片描述
    -(3)提供一个template和一组特例化版本( 例特例化内置指针类型):
    在这里插入图片描述
    在这里插入图片描述

  • Traits classes使得“类型相关信息”在编译期可用。它们以templates和“templates特化”完成实现。整合重载技术( overloading) 后,traitsclasses有可能在编译期对类型执行if…else测试。(上述advance中有类型条件判单,是在运行期执行,可采用重载技术使其在编译期进行,仅在advance函数中调用重载函数即可,如下图)。
    在这里插入图片描述

在这里插入图片描述

  • 如何使用一个traits class:
    (1)建立一组重载函数 (身份像劳工)或函数模板(例如doAdvance) ,彼此间的差异只在于各自的traits参数。令每个函数实现码与其接受之traits信息相应和。.
    (2)建立一个控制函数 (身份像工头)或函数模板(例如advance) ,它调用上述那些“劳工函数”并传递traits class所提供的信息。

条款48:认识模板元编程

  • Template metaprogramming (TMP,模板元编程)可将工作由运行期移往编译期,因而得以实现早期错误侦测和更高的执行效率。
  • TMP可被用来生成“基于政策选择组合”的客户定制代码,也可用来避免生成对某些特殊类型并不适合的代码。
  • 由于template metaprograms执行于C++编译期,因此可将工作从运行期转移到编译期。这导致的一个结果是,某些错误原本通常在运行期才能侦测到,现在可在编译期找出来。另一一个结果是,使用TMP的C++程序可能在每一方面都更高效:较小的可执行文件、较短的运行期、较少的内存需求。然而将工作从运行期移转至编译期的另一个结果是,编译时间变长了
  • TMP中if…else…可通过模板函数重载实现;TMP循环结构可使用递归;TMP递归涉及递归模板具现化,如下图计算阶乘:
    在这里插入图片描述

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

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

相关文章

100. 相同的树

100. 相同的树 题目-简单难度示例1. dfs2. bfs 题目-简单难度 给你两棵二叉树的根节点 p 和 q &#xff0c;编写一个函数来检验这两棵树是否相同。 如果两个树在结构上相同&#xff0c;并且节点具有相同的值&#xff0c;则认为它们是相同的。 示例 示例 1&#xff1a; 输入…

Stable Diffusion XL(SDXL)原理详解

技术报告&#xff1a;SDXL: Improving Latent Diffusion Models for High-Resolution Image Synthesis 官方代码&#xff1a;Stability-AI-generative-models 模型权重&#xff1a;HuggingFace-Stability AI 非官方代码&#xff1a;Linaqruf/kohya-trainer diffuser库&#xf…

Redis实战:Redis的安装及简单使用

本片将介绍 Redis 的安装及简单使用 文章目录 1、Redis安装1.1、Windows下Redis的安装1.2、Linux下Redis的安装1.3、Mac下Redis的安装&#xff08;使用Homebrew&#xff09; 2、Redis使用2.1、启动服务端客户端2.2、Redis简单命令 3、Redis命令大全 1、Redis安装 1.1、Windows…

Redis持久化——AOF

介绍 Redis是运行在内存中的数据库&#xff0c;当我们关闭了Redis服务器后&#xff0c;内存中的数据会丢失吗&#xff1f; 答案是不会的&#xff0c;因为Redis有持久化功能&#xff0c;能够将内存中的数据保存到磁盘中的文件&#xff0c;以此来实现数据的永久保存。 在Redis中…

Spring Clould 消息队列 - RabbitMQ

视频地址&#xff1a;微服务&#xff08;SpringCloudRabbitMQDockerRedis搜索分布式&#xff09; 初识MQ-同步通讯的优缺点&#xff08;P61&#xff0c;P62&#xff09; 同步和异步通讯 微服务间通讯有同步和异步两种方式&#xff1a; 同步通讯&#xff1a;就像打电话&…

步入React正殿 - React组件设计模式

目录 扩展学习资料 高阶组件 /src/components/hoc/withTooltip.js /src/components/hoc/itemA.jsx /src/components/hoc/itemB.jsx /src/App.js 函数作为子组件【Render pprops】 函数作为子组件 /src/components/rp/itemC.jsx【父组件】 /src/components/rp/withToo…

特朗普钱包中持有的以太坊价值高达 500 万美元

根据华盛顿公民责任与道德组织最新发布的经认证的《2023年财务披露信息》&#xff0c;美国前总统唐纳德特朗普持有的以太坊价值高达500万美元。其中&#xff0c;详细条目特别列出了280万美元的收入。此外&#xff0c;特朗普还从NFT INT LLC的NFT授权许可协议中赚取了490万美元。…

Ubuntu系统录屏软件SimpleScreenRecorder安装及使用教程,三分钟学会!

背景&#xff1a;在ubuntu系统调程序时&#xff0c;有时需要录制实验视频&#xff0c;如gazebo仿真环境中机械臂的抓取视频。windows系统最好用的录屏软件非EV录屏莫属&#xff0c;而ubunutu系统下为我觉得SimpleScreenRecorder就很好用&#xff0c;下面介绍SimpleScreenRecord…

【COMP282 LEC1 and LEC2】

LEC 1 1. Printf 在C中的写法 2. Header file 1. 不能写 “.h” 2. strlen变成.size() 3. Namespace 前面用了“using namespace std;” 后面就可以直接写cout 不用写std::cout了 4. Input 就是input是std::cin >> LEC 2 1. Classes 2. 3 access modifiers in C …

美国FDA医疗器械分类目录数据库查询

最近我们在接到FDA医疗器械咨询项目时&#xff0c;经常收到客户关于公司产品在美国FDA医疗器械认证中或是国内所属的产品类别以及如何查询产品分类的疑问。在这里&#xff0c;我将为大家解答这些问题&#xff0c;希望能够提供帮助&#xff01; 美国FDA医疗器械产品目录中包含了…

Python Opencv实践 - 图像均值滤波

import cv2 as cv import numpy as np import matplotlib.pyplot as pltimg cv.imread("../SampleImages/pomeranian.png", cv.IMREAD_COLOR) print(img.shape) pixel_count img.shape[0] * img.shape[1] print(pixel_count)#为图像添加椒盐噪声 #参考资料&#xf…

JAVA调用外部电商API的详情步骤和注意事项

在现代电商生态中&#xff0c;电商API的使用变得越来越普遍。本文将为您详细介绍如何使用JAVA语言调用外部电商API的步骤&#xff0c;并提供一些在开发过程中需要特别注意的事项。希望通过本文的阐述&#xff0c;读者能够对JAVA调用外部电商API有一个全面的了解。 关键词&…

unity发布WebGL遇到的坑(持续更新)

1、unity默认字体在网页中不会显示 解决方法&#xff1a;自己新导入一个字体&#xff0c;使用导入的字体 2、之前打过包并运行过&#xff0c;后面又在unity中进行了修改&#xff0c;重新打包&#xff0c;运行发现还是修改之前的效果&#xff0c;虽然是新包&#xff0c; 解决方…

VTK vtkOBBTree 有向包围盒

vtkOBBTree 有向包围盒 vtkOBBTree是一个包围盒的树&#xff0c;它将体的每个cell分割到每个小的包围盒中&#xff0c;由SetNumberOfBuckets确定每个盒中放多少个 Cell。建立一个vtkOBBTree要先设定DataSet,SetDataSet。然后调用BuildLocator。包围盒精细程度由递归深度 (Max…

Linux问题--docker启动mysql时提示3306端口被占用

问题描述&#xff1a; 解决方法&#xff1a; 1.如果需要kill掉mysqld服务可以先通过 lsof -i :3306 2. 查询到占用3306的PID&#xff0c;随后使用 kill -15 PID 来kill掉mysqld服务。 最后结果

JDK 20下载与安装 (Windows 11系统)

JDK(Java Development Kit)是 Java 语言的软件开发工具包&#xff0c;主要用于移动设备、嵌入式设备上的java应用程序。JDK是整个java开发的核心&#xff0c;它包含了JAVA的运行环境&#xff08;JVMJava系统类库&#xff09;和JAVA工具。 JDK 20 下载 JDK 官网路径&#xff1…

内网穿透实战应用——【通过cpolar分享本地电脑上有趣的照片:发布piwigo网页】

通过cpolar分享本地电脑上有趣的照片&#xff1a;发布piwigo网页 文章目录 通过cpolar分享本地电脑上有趣的照片&#xff1a;发布piwigo网页前言1. 设定一条内网穿透数据隧道2. 与piwigo网站绑定3. 在创建隧道界面填写关键信息4. 隧道创建完成 总结 前言 首先在本地电脑上部署…

机器学习赋能乳腺癌预测:如何使用贝叶斯分级进行精确诊断?

一、引言 乳腺癌是女性最常见的恶性肿瘤之一&#xff0c;也会发生在男性身上。每年全球有数百万人被诊断出乳腺癌&#xff0c;对患者的生活和健康造成了巨大的影响。早期的乳腺癌检测和准确的诊断对于提高治疗的成功率至关重要。然而&#xff0c;乳腺癌的早期诊断面临着许多挑战…

[K8s]问题描述:k8s拉起来的容器少了cuda的so文件

问题解决&#xff1a;需要设置Runtimes&#xff1a;nvidia的同时设置Default Runtimenvidia

JAVA基础知识(六)——异常处理

异常 一、异常概述与异常体系结构二、常见异常三、异常处理机制一&#xff1a;try-catch-finally四、异常处理机制二&#xff1a;throws五、手动抛出异常&#xff1a;throw六、用户自定义异常类七、开发中如何选择使用try-catch-finally还是使用throws八、如何看待代码中的编译…