读书笔记:《C++ 编程规范——101条规则、准则与最佳实践》(3)编程风格

豆瓣链接:《C++ 编程规范——101条规则、准则与最佳实践》


一个人的常量可能是另一个人的变量。——Alan Prelis


第 14 条:宁要编译、链接时错误,也不要运行时错误

以下是一些静态检查的例子:

编译时布尔条件

如果有些布尔值可以在编译期获得并需要检查,可以用 static_assert 代替运行时检查的 assert 。

编译时多态

用 “模板”(编译时多态)代替 “虚函数”(运行时多态)可以减少出错机会。

枚举

用枚举或定义完整的类型来表示符号常量。

向下强制(downcast)

如果程序经常使用 dynamic_cast 或 static_cast,说明基类的设计不够合理。

第 15 条:积极使用 const

能用 const 则尽量使用 const,它可以提供更严格的静态检查。

重载中的 const

需要注意,以下两种声明是等价的:

void f(int x);
void f(const int x);

第 16 条:避免使用宏

因为宏不受任何静态检查的约束,所以它很容易出错。

如:宏无法识别模板参数:

MACRO(F<int, double>)

宏会认为传入的参数是 f

第 17 条:避免使用 “魔数”

避免在程序中,尤其是条件表达式中直接出现字面值,这会让人难以理解,并且使程序难以维护。

if (height < 42) ... // 鬼知道 42 是什么

const min_height = 42;
if (height < min_height) ... // 这下就好理解多了

第 18 条:尽可能声明局部变量

全局变量具有以下缺点:

  • 相关数据的距离被大大拉长,使程序难以理解、维护。
  • 污染上下文名称空间。
  • 静态变量的初始化顺序未定义,容易出错。

例外

  • 有时将变量提出循环是有好处的。
  • 常量不会影响状态,因此本条不适用于常量。

第 19 条:总是初始化变量

下面是一些建议:

使用默认初始值或用 ?:简化变量的定义。

// 初始版本
int a;
if(condition) a = x;
else a =y;

// 修改后的版本
int a = condition? x : y;

用函数代替复杂的计算流,即设计一个初始化函数

// before
int a;
if (condition2)
{
    ... // 一大堆运算
    a = value1;
}
else if (condition2)
{
    ... // 一大堆计算
    a = value2;
}
else
{
    ... // 一大堆计算
    a = value3
}

// after
int init_a()
{
    if (condition2)
    {
        ... // 一大堆运算
        a = value1;
    }
    else if (condition2)
    {
        ... // 一大堆计算
        a = value2;
    }
    else
    {
        ... // 一大堆计算
        a = value3
    }
}

...

int a = init_a();

数组的初始化方式

常见的两种方式:

// 1
char path[MAX_PATH];
path[0] = '\0'; // 仅初始化第一个元素

// 2
char path[MAX_PATH] = {'\0'}; // 初始化全部元素

第 20 条:避免函数过长,避免嵌套过深

以下是对函数设计的建议:

  • 尽量紧凑:一个函数只有一个职责。
  • 不要自我重复:相似的代码用函数代替。
  • 用 && 代替嵌套的 if
  • 不要过分使用 try
  • 优先使用标准算法
  • 用多态函数代替类型标签分支(type tag switch)

第 21 条:便面跨编译单元的初始化依赖

正如多次提到的:静态成员的初始化顺序未知,因此尽量避免相互依赖,循环依赖的情况。

第 22 条:尽量减少定义性依赖,避免循环依赖

简单的循环可以用前向声明解决:

// A,B 互相引用,因此需要前向声明
class A;

class B
{
    A* p;
};

class A
{
    B* p;
};

如果循环链更长,前向声明也会变得复杂。

真正解决问题的手段是 “依赖倒置原则”(Dependency Inversion Principle):不要让高层模块依赖底层模块,而应让两者都依赖于抽象。

依赖倒置原则一般在一些介绍面向对象范式的书中会进行详细介绍。

第 23 条:头文件应该自给自足

就是说一个头文件应包含自己需要的全部东西,若头文件 A 需要头文件 B 的内容,就应该直接在 A 中加入 #include<B> 这段代码,而不是在文档中写:如果要使用头文件 A 的话,用户应自行先引入头文件 B 。

第 24 条:总是编写内部 #include 保护符,绝不要写外部 #include 保护符

常见的头文件保护符格式为:

#ifudef FILENAME_H_INCLUDED_
#define FILENAME_H_INCLUDED_
// 文件的内容
#endif

有些编译器也可以这样写:

#pragma once

当然,这种方式可移植性要差一些。

不过无论用何种方式,一定要保证头文件最多被包含一次。

在一些比较老的书中,可能会介绍网布包含保护符:

#ifndef XXX_H_INCLUDED_
#include "XXX.h"
#define XXX_H_INCLUDED_
#endif

其中 XXX.h 是头文件的实际内容。

这种方式把保护符放在头文件外部,因此叫外部保护符,与之相对的第一种方式叫内部保护符。

这种方式不仅麻烦,且没有任何优势,是一种已经过时的做法,不建议使用。


到这里就结束啦,下一篇记录函数与操作符的部分。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值