本章探讨在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)。
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有两大主要好处:- 表明该方法不会修改对象状态;
- 允许将该方法用于对象的const版本,非const方法不能用于const对象。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)