effective c++ item30-34

news2024/11/18 12:17:48

item30:理解inline

1、inline函数

用inline修饰函数可以防止multiple definition的错误

// foo.h
inline int foo(int x){		// 如果不加inline,在编译时会有两个foo.h被包含进去,导致链接出错
	static int n = 1;
	return x * (n ++);
}
// bar1.cpp
#include "foo.h"
int bar1(){
	return foo(1);
}
// bar2.cpp
#include "foo.h"
int bar2(){
	return foo(2);
}
// main.cpp
int bar1();
int bar2();
int main(){
	int r = bar1() + bar2();
}

2、inline变量(c++17)

// foo.h
struct Foo{
	// 如果不加inline,需要在cpp文件中单独初始化static变量
	inline static int foo = 1;
}
// bar1.cpp
#include "foo.h"
int bar1(){
	return Foo::foo + 1;
}
// bar2.cpp
#include "foo.h"
int bar2(){
	return Foo::foo + 2;
}
// main.cpp
int bar1();
int bar2();
int main(){
	int r = bar1() + bar2();
}

3、修饰命名空间

有利于用来做版本控制

#define macro 2022L
// foo.h
namespace libfoo{
#if macro >= 2022L
	inline
#endif
	namespace libfoo_2022{
		int foo(int );
		float foo(float);
	}
#if macro >= 2019L && macro < 2022L
	inline
#endif
	namespace libfoo_2019{
		int foo(int);
	}
//other version...
}
// main.cpp
using namespace libfoo;
int main(){
	std::cout << foo(5) << std::endl;	// aka libfoo::libfoo_2022::foo(int)
}

以下情况只能用inline来实现:

// foo.h
namespace libfoo{
	class Bar1{};
	// 如果不加inline,会导致ADL(argument-dependent lookup)特性失效
	inline namespace libfoo_2022{	
		void foo1(Bar1);
		class Bar2{};
		template <typename T>
		T &foo(T &);
	}
	void foo2(Bar2);
}
// main.cpp
int main(){
	libfoo::foo(3.2); 	// aka libfoo::libfoo_2022::foo
	libfoo::Bar1 bar;
	libfoo::Bar2 bar2;
	foo1(bar1);			// lib::libfoo_2022::foo1
	foo2(bar2);			// lib::foo2
}

4、隐式inline

class A{
public:
	int geta(){return a;}	// implicit inline request; geta() is defined in a class definition
private:
	int a;
}
inline void f() {... }
void (*pf)() = f;

pf();			// this call won't be, because it's a function pointer
// 该调用不会触发内联,编译器会老老实实进行函数调用

类的空的构造函数不一定就被内联,因为构造函数中要调用基类的构造函数、成员变量的构造函数等,如果都要内联会导致代码过多。

item31:最小化文件依赖|编译防火墙

如果我们修改了某个类的一个成员变量,那么所有包含这个类的文件都要重新编译,为了节约编译的时间我们应该尽量减小文件的依赖。

headle class

Person p(params);
// 如果使用指针就可以避免文件依赖,因为编译器不需要关心对象的内存布局、内存大小,只分配8字节的指针大小就可以
Person *p;

基于此,我们可以将类中的成员做一个前向声明,这也被称为pimpl
在这里插入图片描述使用一个智能指针impl_指向真正的成员实现,当Data、Address发生变化时,Person并不受影响

依赖声明而不是而不是定义

Avoid using objects when object references and pointers will do. You may define references and pointers to a type with only a declaration for the type. Defining objects of a type necessitates the presence of the type’s definition.

Depend on class declarations instead of class definitions whenever you can. Note that you never need a class definition to declare a function using that class, not even if the function passes or returns the class type by value:

class Date;		// class declaration.使用者不需要包含Date.h,只需要依赖于此声明文件即可
Date today(); 		// ok--no definition
void clearAppointments(Date d);		// Date is needed

Provide separate header files for declarations and definitions.

#include "datefwd.h"			// header file declaring(but not defining)

Date today();		// as before
void clearAppointments(Date d);

The name of the declaration-only header file “datefwd.h” is based on the header <iosfwd> from the standard C++ library. <iosfwd> contains declarations of iostream components whose corresponding definitions are in several different headers, including <sstream>…
iosfwd文件:只有一些模版类声明和typedef

interface classes

在这里插入图片描述
Person类便是一个接口

代价

  • 使用pimpl要多一个指针,并且在使用时需要经过一次转调,开销大
  • 使用接口的需要虚函数,内存占用同样多出来一个虚指针,虚函数的调用也需要查找

item32:确定public继承建模出is-a关系

class A : public B
所以A is a B。A一定是B
凡是基类可以包含的内容,派生类也应该可以包含。

item33:避免遮掩继承而来的名称

public

名称遮掩:

int x;		// global variable
void fun(){
	double x;		// local variable
	cin >> x;		// local x
}

在这里插入图片描述
B.func()发生了名称遮蔽,将A的覆盖掉了。违反了item32的is-a的关系。
此时可以做出以下更改:
在这里插入图片描述

private:

使用私有继承,func1便成为了D的私有成员,此时外部访问func1会出错。使用using可以给D访问权限。使用using C::func1声明将类C中的名称func1带入类D的作用域,使类D的成员函数可以访问它。
在这里插入图片描述
如果我们只需要让无参的func1对外公开,使用using就达不到我们想要的结果,此时不论无参还是有参函数都不会报错。
我们只能自己手动重写调用:
在这里插入图片描述
或者这样写:
在这里插入图片描述

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

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

相关文章

【车道线算法】GANet-车道线检测环境配置一文通关

目录 GANet配置全纪录 下载代码 conda环境部署 安装torch和cudatoolkit 安装其他包 编译 总结 GANet配置全纪录 下载代码 GitHub - Wolfwjs/GANet: A Keypoint-based Global Association Network for Lane Detection. Accepted by CVPR 2022 进入代码网址的默认master…

ArcGIS Pro工程

目录 1 工程基础架构 2 工程内容 3 新建工程及工程文件 3.1 工程模板 3.2 工程名称和位置 3.2.1 基于“地图模板”创建新工程 3.2.2 基于“目录模板”创建新工程 3.2.3 基于“全局场景”创建新工程 3.2.4 基于“局部场景”创建新工程 3.3 工程文件 3.3.1 默认地理…

子元素选择器

知识点&#xff1a; 代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8"> <meta http-equiv"X-UA-Compatible" content"IEedge"> <meta name"viewport" c…

【MySQL高级】——用户与权限管理

一、用户管理 <1> 登录 mysql –h hostname|hostIP –P port –u username –p DatabaseName –e "SQL语句"-h参数 后面接主机名或者主机IP&#xff0c;hostname为主机&#xff0c;hostIP为主机IP。 -P参数 后面接MySQL服务的端口&#xff0c;通过该参数连接…

序列检测和序列发生器——verilog代码实现

文章目录 前言一、序列检测器1.1 重复序列检测1.1.1 序列缓存对比/移位寄存器法1.1.2 状态机法 1.2 非重复序列检测 二、序列发生器2.1 移位寄存器法2.2 反馈法2.3 计数器法 前言 2023.4.25 2023.4.26 学习打卡&#xff0c;天气转晴 一、序列检测器 1.1 重复序列检测 1.1.1 …

HTML基础标签

目录 1.html文件结构 2.注释 3.文本标签 4.图片 5.音频与视频 6.超链接 7.表单 8.列表&#xff08;可以嵌套&#xff09; 无序列表 有序列表 定义列表 9.表格 10.语义标签 11.特殊符号 1.html文件结构 <!-- 文档类型声明 --> <!DOCTYPE html> <html>…

学系统集成项目管理工程师(中项)系列12_干系人管理

1. 要管理干系人的期望&#xff0c;更要保证他们的适度参与&#xff0c;而后者是项目成功非常关键的因素之一 1.1. 识别干系人及其信息 1.2. 评估关键干系人的诉求和影响力 1.3. 对干系人分类 1.4. 制定干系人管理计划 1.5. 【19上选56】 2. 识别干系人 2.1. 典型干系人…

如何解决宝塔面板nginx占用80端口的问题

前言: 由于使用Docker部署前端项目老是报错说80端口被占用,所以不得不去查找原因并且解决 上网查了很多资料说修改80端口这对我(有点强迫症)来说修改让我很难受 开始: 我们去找到虚拟机的这个目录 /www/server/panel/vhost/nginx 然后直接修改下面的文件 修改文件的端口 最…

windows中python安装保姆教程

猜你感兴趣 牛逼的python库-使用Pyinstaller将python打包成exe使用python实现自动点击功能python进程&#xff0c;线程&#xff0c;协程简介快速搭建私有pip镜像源 简介 Python 是一种开源的解释型脚本编程语言&#xff0c;Python简单易用&#xff0c;学习成本低&#xff0c;…

ChatGLM-6B的P-Tuning微调详细步骤及结果验证

文章目录 1. ChatGLM-6B1.1 P-Tuning v2简介 2. 运行环境2.1 项目准备 3.数据准备4.使用P-Tuning v2对ChatGLM-6B微调5. 模型评估6. 利用微调后的模型进行验证6.1 微调后的模型6.2 原始ChatGLM-6B模型6.3 结果对比 1. ChatGLM-6B ChatGLM-6B仓库地址&#xff1a;https://githu…

<<c和指针>>温故及问题研讨(第三章)

第三章-数据 1. 前言2. 基本数据类型2.1 整型家族2.2 字面值常量 3. 基本声明3.1 数组的声明以及引用3.2 指针的声明注意事项3.3 隐式声明 4. 常量5. 作用域5.1 代码块作用域5.2 文件作用域5.3 原型作用域 6. 链接属性6.1 链接属性分类以及作用范围6.2 关键字:extern和static6.…

数据库基础篇 《18.MySQL8其它新特性》

第18章_MySQL8其它新特性 1. MySQL8新特性概述 MySQL从5.7版本直接跳跃发布了8.0版本&#xff0c;可见这是一个令人兴奋的里程碑版本。MySQL 8版本在功能上做了显著的改进与增强&#xff0c;开发者对MySQL的源代码进行了重构&#xff0c;最突出的一点是多MySQL Optimizer优化…

GPT详细安装教程-GPT软件国内也能使用

GPT (Generative Pre-trained Transformer) 是一种基于 Transformer 模型的自然语言处理模型&#xff0c;由 OpenAI 提出&#xff0c;可以应用于各种任务&#xff0c;如对话系统、文本生成、机器翻译等。GPT-3 是目前最大的语言模型之一&#xff0c;其预训练参数超过了 13 亿个…

LeetCode:206. 反转链表

&#x1f34e;道阻且长&#xff0c;行则将至。&#x1f353; &#x1f33b;算法&#xff0c;不如说它是一种思考方式&#x1f340; 算法专栏&#xff1a; &#x1f449;&#x1f3fb;123 一、&#x1f331;206. 反转链表 题目描述&#xff1a;给你单链表的头节点 head &#x…

Sharding-JDBC之垂直分库水平分表

目录 一、简介二、maven依赖三、数据库3.1、创建数据库3.2、订单表3.3、用户表 四、配置&#xff08;二选一&#xff09;4.1、properties配置4.2、yml配置 五、实现5.1、实体5.2、持久层5.3、服务层5.4、测试类5.4.1、保存订单数据5.4.2、查询订单数据5.4.3、保存用户数据5.4.4…

Android SeekBar控制视频播放进度(二)——seekTo()不准确

Android SeekBar控制视频播放进度二——seekTo不准确 简介seekTo()视频帧 和 视频关键帧解决办法方法一方法二 简介 上一篇文章中&#xff0c;我们介绍了使用SeekBar控制视频播放&#xff0c;使用过程中发现&#xff0c;对于一些视频&#xff0c;我们拖动SeekBar进度条调节播放…

喜报 | ScanA内容安全云监测获评“新一代信息技术创新产品”

4月20日&#xff0c;在赛迪主办的2023 IT市场年会上&#xff0c;“年度IT市场权威榜单”正式发布。 知道创宇的ScanA内容安全云监测产品荣获“新一代信息技术创新产品”奖项。作为中国IT业界延续时间最长的年度盛会之一&#xff0c;历届IT市场年会公布的IT市场权威榜单已成为市…

备份数据看这里,免费教你苹果手机怎么备份所有数据!

案例&#xff1a;苹果手机怎么算备份成功&#xff1f; 【友友们&#xff0c;手机恢复出厂设置前&#xff0c;怎么样可以备份苹果手机里面的所有数据&#xff1f;】 苹果手机备份数据对于用户来说是非常重要的。在备份数据的同时&#xff0c;还需要学会如何恢复误删的数据。那么…

【微服务笔记22】微服务组件之Sentinel控制台的使用(Sentinel Dashboard)

这篇文章&#xff0c;主要介绍微服务组件之Sentinel控制台的使用&#xff08;Sentinel Dashboard&#xff09;。 目录 一、Sentinel控制台 1.1、下载Dashboard控制台 1.2、搭建测试工程 &#xff08;1&#xff09;引入依赖 &#xff08;2&#xff09;添加配置信息 &#…

微服务生态 -- dubbo -- dubbo3应用级别服务发现(阅读官方文档)

服务发现概述 从 Internet 刚开始兴起&#xff0c;如何动态感知后端服务的地址变化就是一个必须要面对的问题&#xff0c;为此人们定义了 DNS 协议&#xff0c;基于此协议&#xff0c;调用方只需要记住由固定字符串组成的域名&#xff0c;就能轻松完成对后端服务的访问&#x…