Effective C++ 条款31:将文件间的编译依存关系降至最低

news/2025/1/1 23:26:38/

文章目录

    • 条款31:将文件间的编译依存关系降至最低
      • 最小化编译依赖关系的最佳实践
      • 通过减少编译依赖的好处
      • 总结

条款31:将文件间的编译依存关系降至最低

为了减少编译依赖关系,应该将接口与实现分离,并尽量减少头文件之间的依赖。这有助于加快编译速度,降低因代码变化引起的编译重新构建的时间。

最小化编译依赖关系的最佳实践

  1. 分离接口和实现
    将类的接口和实现分开,通常做法是将接口声明放在头文件中,而将实现代码放在源文件中。这样做可以避免头文件频繁改变导致的重新编译。
// Widget.h: 声明接口
class Widget {
public:void display();
};// Widget.cpp: 实现
#include "Widget.h"
void Widget::display() {// 实现代码
}
  1. 使用 object reference 或 object pointer 替代 object
    当使用对象时,如果对象引用或指针足以完成任务,尽量不要直接传递整个对象。通过引用或指针传递可以减少对象的拷贝,降低编译时依赖。
// 如果只需要访问对象,可以使用引用
void processWidget(const Widget& widget);  // 只传递引用
  1. 使用 class 声明式替换 class 定义式
    为了减少编译依赖,应该尽量在头文件中只提供类声明,而将类的实现放在源文件中。通过这种方式,其他文件仅依赖于声明,减少了编译时的依赖性。
// Widget.h: 仅声明
class Widget;// Widget.cpp: 定义
#include "Widget.h"
void Widget::display() {// 实现代码
}
  1. 使用 Handle class 或 Interface class
    使用 “Handle class” 和 “Interface class” 是一种常见的降低编译依赖的技术。Handle class 通常是一个不包含数据的类,只包含指针或者引用,避免了类的完整定义暴露。Interface class 是一个纯虚类,表示类的接口,所有实现细节都隐藏在派生类中。
// WidgetHandle.h: 声明类的接口
class WidgetHandle {
public:virtual void display() = 0;  // 纯虚函数
};// WidgetHandle.cpp: 实现
#include "WidgetHandle.h"
// 实现函数
  1. 使用声明式和定义式的不同头文件
    通过将声明和定义分开到不同的头文件中,可以使头文件的编译依赖最小化。声明文件只包含类的接口,而定义文件包含类的实现。
// WidgetDecl.h: 声明
class Widget;// WidgetDef.h: 定义
#include "WidgetDecl.h"
class Widget {
public:void display() { ... }
};

通过减少编译依赖的好处

  • 加快编译速度:减少依赖关系的传递,避免无关代码的重新编译,减少编译时间。
  • 提高可维护性:代码修改时不必修改过多的依赖文件,降低了维护成本。
  • 提高灵活性:依赖于声明而不是定义使得系统的扩展性和灵活性更高。修改实现不需要重新编译所有依赖该实现的文件。

总结

  • 分离接口和实现:通过分离接口和实现,减少了文件之间的依赖关系。
  • 引用或指针传递:避免直接传递对象,尽量使用引用或指针来减少拷贝和依赖。
  • 声明式替代定义式:尽可能在头文件中只提供声明,避免暴露实现细节。
  • 使用 Handle 和 Interface 类:通过 handle 类和接口类设计模式来最小化依赖关系,增强系统的灵活性。

减少编译依赖关系是提升大型项目可维护性和编译效率的关键,遵循这些原则有助于构建高效且易于扩展的系统。


http://www.ppmy.cn/news/1559427.html

相关文章

电商数据的安全与隐私保护:API接口的角色

在电子商务领域,数据安全与隐私保护是企业运营和消费者信任的核心。随着电商平台的日益复杂化和互联网技术的快速发展,API(应用程序接口)作为系统间通信的桥梁,在数据安全与隐私保护中扮演着至关重要的角色。本文将从A…

DFS【东北大学oj数据结构11-2】C++

题面 深度优先搜索(DFS)是一种基于尽可能多地访问相邻顶点策略的图搜索算法。如果顶点 v 有未搜索的顶点则递归搜索直至 v 的最后一条边。在搜索了 v 的所有边之后,搜索继续返回到找到 v 时经过的边。 搜索从原来的起点开始,直到…

stm32基础(keil创建、Proteus仿真、点亮LED灯,7段数码管)

一、keil的创建 随后点击新建(Ctrln),接着保存到所自己项目工程文件。.c .h都是这样操作 二、Proteus的简单使用 左上角框框内可以拖动 三、点亮LED灯代码 led.c #include "stm32f10x.h" // Device headervoid led_init(…

HTTP3详解

最近网上看到了相关HTTP 3的文章,觉得很不错,这里整理记录一下,仅供学习参考。 你连 HTTP2 都还没搞明白,就有人开始谈 HTTP3 了,真让人火大。但 HTTP3 会受到关注也是有理由的:它速度很快。 1、很久以前 …

ES7+ React/Redux/GraphQL/React-Native snippets 使用指南

VS Code React Snippets 使用指南 目录 简介基础方法React 相关React Native 相关Redux 相关PropTypes 相关控制台相关React 组件相关 简介 ES7 React/Redux/GraphQL/React-Native snippets 是一个用于 VS Code 的代码片段插件,它提供了大量用于 React 开发的代…

asp.net 高校学生勤工俭学系统设计与实现

博主介绍:专注于Java(springboot ssm 等开发框架) vue .net php python(flask Django) 小程序 等诸多技术领域和毕业项目实战、企业信息化系统建设,从业十五余年开发设计教学工作 ☆☆☆ 精彩专栏推荐订阅☆☆☆☆☆不然下次找…

Linux | 零基础Ubuntu卸载MySQL Server 零痕迹

目录 介绍 移除MySQL软件包 自动移除依赖项 清理残留文件 检查是否还有残留文件 重启系统 介绍 难免会出现一些迷人的操作,让整个数据库都作废了,又改不了文件,修复不了问题,只能重装了,但又卸载不干净&#xf…

Rust : tokio中select!

关于tokio的select宏,有不少的用途。包括超时和竞态选择等。 关于select宏需要关注,相关的异步条件,会同时执行,只是当有一个最早完成时,会执行“抛弃”和“对应”策略。 说明:对本文以下素材的来源表示感…