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.

posted on 2012-12-06 19:20  好好单调  阅读(287)  评论(0编辑  收藏  举报