《C++ API设计》第6章 C++用法读书笔记

《C++ API设计》第6章 C++用法读书笔记,第1张

本章探讨在C++中哪些特征有助于编写良好的API。许多C++具体风格的选择会影响API的,比如名字空间、 *** 作符等概念的使用。

6.1 命名空间

API中添加命名空间有两种流行的做法。

方法一 给所有的公有API符号添加唯一前缀

优势在于它也适用于纯 C API。

这样使用命名空间的例子有很多,例如OpenGL API “gl”作为所有公有符号的前缀。

方法二 使用namespace关键字

本质是定义了一个作用域,在这个作用域内的所有名字都被添加了一个额外的前缀标识符。

这种风格的好处是你不必小翼翼地确保每一个类、函数、枚举和常量具有一致的前缀,因为编译器会为你做这件事。你也可以创建嵌套的命名空间,形成命名空间树。例如,boost::detail::variant。

坏处是使用命名空间特性会产生冗长的符号名,尤其是那些包含在几层嵌套命名空间中的符号。通过使用using关键字解决这个问题,例如using ch = std::chrono

任何时候都不要在公用API头文件的全局作用域内使用using关键字!这样做会导致所引用命名空间的全部符号在全局命名空间可见。这便破坏了使用命名空间的初衷。

6.2 构造函数和赋值

编译器能够为以下4种类的特殊方法成默认的版本。

默认构造函数

析构函数

如果没有为类编写析构函数,编译器会自动生成。编译器也会生成代码,自动为所有的成员变量调用析构函数,调用顺序与它们在类声明中出现的顺序相反。

复制构造函数

如果没有为类定义复制构造函数,编译器会自动生成,它执行对已有对象成员变量的浅层复制。

如果为对象分配了资源,就需要使用复制构造函数执行深层复制。

调用复制构造函数的情形

  • 对象以传值方式传递给方法或返回;
  • 对象使用下述语法初始 MyClass a = b;
  • 对象位于在花括号中的初始化列表内;
  • 对象在异常中被抛出或捕获。

赋值 *** 作符

实现赋值 *** 作符的一些指导原则

  • 为右侧 *** 作数使用const引用;
  • 以引用方式返回*this, 以支持 *** 作符链;
  • 在设置新状态前销毁已存在的状态;
  • 通过比较this和&rth检测自赋值(a = a)。
如果想创建不能被复制的对象,则应将复制构造函数和赋值 *** 作符声明为类的私有成员,或使用boost::noncopyable。 如果类分配了资源,则应该遵循“三大件”规则,同时定义析构函数、复制构造函数和赋值 *** 作符。 6.2.1 控制编译生成的函数 C++98标准中,开发人员几乎不能控制编译器自动生成这些特殊函数的行为。 在新的C++0x规范中,可以显式控制编译器生成或不生成这些函数。例如,下面的代码
class MyClass
{
public:
    virtual ~MyClass() = default;
private:
    MyClass() = default;
};
也可以让编译器禁用某些默认生成的函数,例如,下面的代码
class NonCopyable
{
public:
    NonCopyable() = default;
    NonCopyable(const NonCopyable&) = delete;
    NonCopyable & operator¼(const NonCopyable&) = delete;
};
6.2.2 定义构造函数和赋值 *** 作符

无重要内容

6.2.3 explicit关键字 为那些只接受一个参数的构造函数添加explicit是一种好的做法,用于阻止构造对象时特定的构造函数被隐式调用。 同样可以把复制构造函数声明为explicit的。这会阻止复制构造函数的隐式调用。 6.3 const正确性 const正确性是指使用C++的const关键字将变量或者方法声明为不可变的。 它表达方法的意图 ,从而使这些方法更加易用。 6.3.1 方法的const正确性 将函数声明为const有两大主要好处
  1. 表明该方法不会修改对象状态;
  2. 允许将该方法用于对象的const版本,非const方法不能用于const对象。
const方法使用方式的两个阵营 一个是位元常量性(bitwise constness)阵营, 他们认为const方法不应该修改类的任何成员变量; 另一个是逻辑常量性(logical constness)阵营,他们认为如果const方法对成员变量的修改不能被用户感知,那么const方法就可以修改成员变量。 C++编译器遵从位元的方法。可以通过将变量声明为mutable使编译器表现出逻辑常量性方式。 尽可能早地将函数和参数声明为const,过后修正API中的const正确性既耗时又麻烦。 6.3.2 参数的const正确性 可以使用const关键字表明将一个参数设计为输入参数还是输出参数。 当向const函数传入引用或指针时,也要考虑该参数是否可以声明为const。 6.3.3 返回值的const正确性 将函数返回结果声明为const的主要理由是其引用了对象的内部状态。 如果返回指向私有数据成员的指针或引用,那么应该把返回结果声明为const。这种情况下,还必须考虑返回的指针或引用是否会比类存在得更久。如果有这个可能,就应该考虑返回一个引用计数指针,例如shared_ptr。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://www.outofmemory.cn/langs/866790.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-12
下一篇 2022-05-12

发表评论

登录后才能评论

评论列表(0条)

保存