Google开源项目风格指南——类
对单个参数的构造函数使用 C++ 关键字 explicit
定义:
通常, 如果构造函数只有一个参数, 可看成是一种隐式转换. 打个比方, 如果你定义了 Foo::Foo(string name), 接着把一个字符串传给一个以 Foo 对象为参数的函数, 构造函数 Foo::Foo(string name) 将被调用, 并将该字符串转换为一个 Foo 的临时对象传给调用函数. 看上去很方便, 但如果你并不希望如此通过转换生成一个新对象的话, 麻烦也随之而来. 为避免构造函数被调用造成隐式转换, 可以将其声明为 explicit.优点:避免不合时宜的变换.缺点:无结论:
所有单参数构造函数都必须是显式的. 在类定义中, 将关键字 explicit 加到单参数构造函数前: explicit Foo(string name);
例外: 在极少数情况下, 拷贝构造函数可以不声明成 explicit. 作为其它类的透明包装器的类也是特例之一. 类似的例外情况应在注释中明确说明.
以上引用于Google开源项目风格指南第三节。
http://zh-google-styleguide.readthedocs.org/en/latest/google-cpp-styleguide/classes/
原来类的单个参数构造函数,在不使用explicit关键字进行显示声明的情况下,可以自动转换生成对应的参数类型。
例:
//explicit class CSample { public: CSample::CSample(){}; explicit CSample::CSample(int a) { m = a; } int m; }; void f(CSample noSample) { return; } void main() { f(1); return; }
上述代码如果除去关键字explicit,则可以编译通过。加上关键字explicit则表明要显示的调用单个参数的构造函数。
拷贝构造函数
Tip
仅在代码中需要拷贝一个类对象的时候使用拷贝构造函数; 大部分情况下都不需要, 此时应使用 DISALLOW_COPY_AND_ASSIGN.
- 定义:
- 拷贝构造函数在复制一个对象到新建对象时被调用 (特别是对象传值时).
- 优点:
- 拷贝构造函数使得拷贝对象更加容易. STL 容器要求所有内容可拷贝, 可赋值.
- 缺点:
- C++ 中的隐式对象拷贝是很多性能问题和 bug 的根源. 拷贝构造函数降低了代码可读性, 相比传引用, 跟踪传值的对象更加困难, 对象修改的地方变得难以捉摸.
- 结论:
-
大部分类并不需要可拷贝, 也不需要一个拷贝构造函数或重载赋值运算符. 不幸的是, 如果你不主动声明它们, 编译器会为你自动生成, 而且是 public 的.
- 可以考虑在类的 private: 中添加拷贝构造函数和赋值操作的空实现, 只有声明, 没有定义. 由于这些空函数声明为 private, 当其他代码试图使用它们的时候, 编译器将报错. 方便起见, 我们可以使用 DISALLOW_COPY_AND_ASSIGN 宏:
-
// 禁止使用拷贝构造函数和 operator= 赋值操作的宏 // 应该类的 private: 中使用 #define DISALLOW_COPY_AND_ASSIGN(TypeName) \ TypeName(const TypeName&); \ void operator=(const TypeName&)
- 在 class foo: 中:
-
class Foo { public: Foo(int f); ~Foo(); private: DISALLOW_COPY_AND_ASSIGN(Foo); };
如上所述, 绝大多数情况下都应使用 DISALLOW_COPY_AND_ASSIGN 宏. 如果类确实需要可拷贝, 应在该类的头文件中说明原由, 并合理的定义拷贝构造函数和赋值操作. 注意在 operator= 中检测自我赋值的情况 (yospaly 注: 即 operator= 接收的参数是该对象本身).
为了能作为 STL 容器的值, 你可能有使类可拷贝的冲动. 在大多数类似的情况下, 真正该做的是把对象的 指针 放到 STL 容器中. 可以考虑使用 std::tr1::shared_ptr.