effective c++ item40-44

news2024/10/5 17:18:23

item40:谨慎的使用多重继承

多重继承带来的符号的歧义性

在这里插入图片描述
消除歧义性

#include <iostream>
#include <vector>
using namespace std;
class A {
public:
  void f() { cout << "A" << endl; }
};
class B {
private:
  void f();
};
class C : public A, public B {};
int main() {
  C c;
  c.A::f();
}

钻石形多重继承

在这里插入图片描述
on the one hand, it inherits a copy from each of its base classes, so that suggests that IOFile should have two fileName data members. On the other hand, simple logic says that an IOFile object has only one file name, so the fileName field it inherits through its two base classes should not be replicated.

virtual虚继承

解决了多重继承的问题
在标准库中,basic istream和basic ostream库都是虚继承自basic ios的类,而basic iostream又继承自basic istream和basic ostream。

virtual继承的成本

objects created from classes using virtual inheritance are generally larger than they whould be without virtual inheritance. Access to data members in virtual base classes is also slower than to those in non-virtual base classes. The details vary from compiler to compiler, but the basic thrust is clear: virtual inheritance costs.

It costs in other ways, too. The rules governing the initialization of virtual base classes are more complicated and less intuitive than are those for non-virtual bases.

虚基类的初始化问题

class A{
public: 
	A(A* a);
};

class B:virtual public A{
public: 
	B(B* a):A(a){};
};

class C{
public: 
	C(C* a):A(a){};
};

class D:public B, public C{
public: 
	D(D* a):B(a), C(a){};	// compile error
	D(D* a):A(a), B(a), C(a){};		// correct
};

class E:public D{
public: 
	E(E* a):D(a){};			// compile error
	E(E* a):A(a), E(a){};		// correct
};

虚继承成本高,要维护基类

使用多重继承

item41:了解隐式接口和编译期多态

显示接口和运行期多态

class Widget{
public:
	virtual std::size_t size() const;
	virtual void normalize();
}
void doProcessing(Widget& w){
	if(w.size() > 10 && w != someWidget){
		Widget temp(w);
		temp.normalize();
		temp.swap(w);
	}
}

使用虚函数可以实现运行期的多态。

隐式接口和编译期多态

template<typename T>
void doProcessing(T& w){
	if(w.size() > 10 && w != someWidget){
		T temp(w);
		temp.normalize();
		temp.swap(w);
	}
}

在编译期做类型推导,得到T的类型。实现编译期多态
不论T是什么类型,其中必须要有size、normalize、swap、!=等接口。

item42:理解typename的双重含义

template<class T> class Widget;
template<typename T> class Widget;

class不能替代typename,但是typename可以替代class

template<typename C>
void print2nd(const C &constainer){		// C被称为从属名称
	if(constainer.size() > 2){
		// 这一行将会报错!!!!原因在下面
		C::const_iterator iter(constainer.cbegin());	// C::const_iterator被称为嵌套从属名称
		++ iter;
		std::cout << *iter << std::endl;
	}
}
int main(){
	std::vector<int> v{1,2,3,4};
	print2nd(v);
	return 0;
}

上面出错的语句原因不太直观,可以参考如下语句:

C::const_iterator * x;

编译器可能会以为在C中有const_iterator类型的成员,然后✖️x,解决方法为在嵌套从属名称前加typename:

typename C::const_iterator * x;		// 告知编译器后面是一个类型

typename使用规则也有例外:

  • 在以下这种情况下不需要加type name
template<typename T>
class Derived:public Base<T>::Nested{		// base class list:typename not allowed
public:
	// base class indetifier in mem.init.list:typename not allowed
	explicit Derived(int x):Base<T>::Nested(x){	
		// use of nested dependent type name:typename
		typename Base<T>::Nested temp;
	}
};

另外,还可以使用typedef或者using来简化编程:

template<typename IterT>
void workWithIterator(IterT iter){
	typename std::iterator_traits<IterT>::value_type temp(*iter);
}
// use typedef
template<typename IterT>
void workWithIterator(IterT iter){
	typedef typename std::iterator_traits<IterT>::value_type value_type;
	value_type temp(*iter);
}

item43:如何访问模版基类内的名称

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

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

相关文章

5.5.1哈夫曼树

知识总览&#xff1a; 概念&#xff1a; 结点的权&#xff1a;有某种现实含义的数值&#xff08;如&#xff1a;表示结点的重要性&#xff09; 结点的带权路径长度&#xff1a;从树的根到该结点的路径长度&#xff08;经过的边数&#xff09;与该结点上权值的乘积。 就比如说要…

ETL工具 - Kettle 案例,拉取网络列表数据

一、Kettle 实战案例 上篇文章对 Kettle 的查询、连接、统计、脚本算子进行了介绍&#xff0c;对 Kettle 的大部分算子都应该有了相应的了解&#xff0c;下面我们基于 Kettle 实战案例&#xff0c;拉取 CSDN 博客列表的全部数据&#xff0c;存放至 Excel 文件中。 实验之前先…

NECCS|全国大学生英语竞赛C类|词汇和语法|词汇题|21:03~21:53

词汇题 语法题 情景对话题 目录 一、词汇题 1. 基本词义辨析题 2. 同义词或近义词辨析题 3. 固定搭配 二、常见词组 一、词汇题 1. 基本词义辨析题 appropriate funds 拨款 slum- clearance programme 贫民窟清理计划 reject 拒绝接受&…

DAY 49 tomcat服务配置优化

什么是Tomcat Tomcat是Java 语言开发的&#xff0c;Tomcat 服务器是一个免费的开放源代码的Web应用服务器&#xff0c;是Apache 软件基金会的 Jakarta 项目中的一个核心项目&#xff0c;由Apache、Sun和其他一些公司及人共同开发而成。 Tomcat属于轻量级应用服务器&#xff0…

外卖项目优化-02-

文章目录 瑞吉外卖项目优化-Day02课程内容前言1. MySQL主从复制1.1 介绍1.2 搭建1.2.1 准备工作1.2.2 主库配置1.2.3 从库配置 1.3 测试 2. 读写分离案例2.1 背景介绍2.2 ShardingJDBC介绍2.3 数据库环境2.4 初始工程导入2.5 读写分离配置2.6 测试 3. 项目实现读写分离3.1 数据…

深入解析PyTorch中的基本数据结构:张量的维度、形状和数据类型

❤️觉得内容不错的话&#xff0c;欢迎点赞收藏加关注&#x1f60a;&#x1f60a;&#x1f60a;&#xff0c;后续会继续输入更多优质内容❤️ &#x1f449;有问题欢迎大家加关注私戳或者评论&#xff08;包括但不限于NLP算法相关&#xff0c;linux学习相关&#xff0c;读研读博…

【LEAP模型】能源环境发展、碳排放建模预测及不确定性分析

本次内容突出与实例结合&#xff0c;紧密结合国家能源统计制度及《省级温室气体排放编制指南》&#xff0c;深入浅出地介绍针对不同级别研究对象时如何根据数据结构、可获取性、研究目的&#xff0c;构建合适的能源生产、转换、消费、温室气体排放&#xff08;以碳排放为主&…

【Spring框架全系列】Spring更简单的读取和存储对象

&#x1f4ec;&#x1f4ec;哈喽&#xff0c;大家好&#xff0c;我是小浪。上篇博客我们介绍了如何创建一个spring项目&#xff0c;并且如何的存、取对象&#xff0c;介绍了相关方法&#xff0c;那么本篇博客将接着上篇博客的内容介绍如何更加简单的读取和存储对象。 &#x1f…

从源码角度看Linux进程组和线程组

1.进程ID 线程组ID&#xff1a; 设置了CLONE_THREAD flag创建的进程(线程&#xff09;同属于同一个线程组&#xff0c;拥有同一个线程组ID(TGID)。pthread_create创建线程的时候&#xff0c;底层通过clone函数实现就指定了CLONE_THREAD参数&#xff0c;即一个进程中的各个线程…

前端搭建猜数字游戏(内附源码)

The sand accumulates to form a pagoda ✨ 写在前面✨ 功能介绍✨ 页面搭建✨ 样式设置✨ 逻辑部分✨ 完整代码 ✨ 写在前面 上周我们实通过前端基础实现了打字通&#xff0c;当然很多伙伴再评论区提出了想法&#xff0c;后续我们会考虑实现的&#xff0c;今天还是继续按照我…

架构设计-数据库篇

大家好&#xff0c;我是易安&#xff01; 之前我们讲过架构设计的一些原则&#xff0c;和架构设计的方法论&#xff0c;今天我们谈谈高性能数据库集群的设计与应用。 读写分离原理 读写分离的基本原理是将数据库读写操作分散到不同的节点上&#xff0c;下面是其基本架构图。 读…

【ansys】project may be corrupted and recovery information is available

一、问题背景 在网上找一个fluent算例打算在自己机器上运行。 打开fluent求解器&#xff0c;因为路径上有中文&#xff0c;在求解计算的时候出错了。 于是我通过任务管理器强制退出fluent和workbench程序&#xff0c;再将项目文件复制到一个没有中文的目录路径中。 重新打开…

15-2-线程-线程的创建,等待,退出

一、相关API 1. 线程创建 1. 线程创建 #include <pthread.h> int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg);参数&#xff1a;参数1&#xff1a;&#xff08;创建的线程 的地址…

【JavaEE】TCP回写服务器简易翻译服务器(网络编程)

博主简介&#xff1a;想进大厂的打工人博主主页&#xff1a;xyk:所属专栏: JavaEE初阶 上一篇我们讲解了UDP回写服务器和简易翻译服务器&#xff0c;想了解本篇文章&#xff0c;建议先看看上篇文章&#xff0c;学起来会更容易一些~~传送门&#xff1a;(1条消息) 【JavaEE】UDP数…

创新案例|香氛新品牌观夏如何以DTC模式仅4年实现年收过亿

国产香氛品牌观夏的DTC战略&#xff0c;正是从产品创新、全渠道布局、社交电商营销等方面创新&#xff0c;实现更高效地直接触达和转化消费者。观夏作为香氛DTC品牌的创新模式值得更多国内新品牌的关注与借鉴&#xff0c;同时也能为传统品牌的DTC转型提供全球化视野的启示。 1.…

改进YOLOv8: | ICLR 2022 | 涨点神器!Intel提出ODConv:即插即用的动态卷积 | 轻量化涨点创新必备

OMNI-DIMENSIONAL DYNAMIC CONVOLUTION ODConv实验核心代码修改文件yaml文件运行论文链接: https://openreview.net/forum?id=DmpCfq6Mg39 本文介绍了一篇动态卷积的工作:ODConv,其通过并行策略采用多维注意力机制沿核空间的四个维度学习互补性注意力。作为一种“即插即用…

3。数据结构(1)

嵌入式软件开发第三部分&#xff0c;各类常用的数据结构及扩展&#xff0c;良好的数据结构选择是保证程序稳定运行的关键&#xff0c;&#xff08;1&#xff09;部分包括数组&#xff0c;链表&#xff0c;栈&#xff0c;队列。&#xff08;2&#xff09;部分包括树&#xff0c;…

使用rt thread studio新建一个rt thread工程的详细操作说明(以stm32F411CEU6)为例

新建工程 这里以rt thread 5.0以及stm32F411CEU6芯片为例&#xff0c;创建工程 先建一个工作空间 .metadata是建工作空间自己生成的。 这时候&#xff0c;工作空间是空的&#xff0c;没有项目: 新建项目 首先下载RT-thread源文件和芯片支持包&#xff1a; 2023.05.02&#x…

NOIP2000 提高组 方格取数 线性DP 坐标优化 全局最优

&#x1f351; 算法题解专栏 &#x1f351; [NOIP2000 提高组] 方格取数 题目描述 设有 N N N \times N NN 的方格图 ( N ≤ 9 ) (N \le 9) (N≤9)&#xff0c;我们将其中的某些方格中填入正整数&#xff0c;而其他的方格中则放入数字 0 0 0。如下图所示&#xff08;见样…

延时队列的三种实现方案

延时队列的三种实现方案 什么是延时队列延时队列的应用场景基于Java DelayQueue的实现源码剖析 基于Redis的zset实现实现步骤Redis延时队列优势Redis延时队列劣势 基于RabbitMQ的延时队列实现TTL DXL(死信队列)插件实现 总结参考文章 什么是延时队列 在分布式系统中&#xff…