Linux | c&cpp | Email | github | QQ群:425043908 关注本站

itarticle.cc

您现在的位置是:网站首页 -> 代码相关 文章内容

禁用自动生成的函数(定义且不实现)-itarticl.cc-IT技术类文章记录&分享

发布时间: 8年前代码相关 122人已围观返回

如果想让你的类定义出来的对象是独一无二的,即对象无法被复制,或者使用赋值操作符赋给另外一个对象,那么最好的方法就是禁用拷贝构造函数和赋值操作符。下面介绍几种禁用的方法。(方法来自Effective C++,如果想禁用类的其他函数,方法类似)(Effective C++之06)


1. 定义为private且不实现它

我们知道,拷贝构造函数和赋值操作符重载函数,即使不定义,编译器也会生成一个默认的函数。但是如果定义了,class还是会支持这两个函数。那么应该怎么去禁用它们呢?

在C++中,如果不想让对象调用某个方法,那么可以将这个方法声明为private,因此,我们可以将拷贝构造函数和赋值操作符重载函数声明为private,就可以阻止别人调用它了。但是,private函数还是可以在类的成员函数和friend函数中调用。这里还有一个技巧,就是将函数定义为private而且不实现它。

class SpecialClass {

...

private:

SpecialClass(const SpecialClass&);

SpecialClass& operator=(const SpecialClass&);

};

将SpecialClass这样定义,并且不实现这两个函数,那么如果有人试图拷贝这个类的对象,编译器就会报错:

SpecialClass sc1;

SpecialClass sc2(sc1); //error, 编译出错

SpecialClass sc3;

sc3 = sc1; //error, 编译出错

而且即使在成员函数或者friend函数中调用了它,链接时也会出错。


2. 继承Uncopyable类

第一种方法可以解决禁用拷贝构造函数的问题,但是还有一点不完美的是,如果用户不小心在成员函数或者friend函数中调用了它,那么这个错误只有到链接阶段才能被发现。所以就有了继承一个Uncopyable类的方法:

class Uncopyable {

protected:

Uncopyable() {}

~Uncopyable() {}

private:

Uncopyable(const Uncopyable&);

Uncopyable& operator=(const Uncopyable&);

};

此时,只需要继承Uncopyable类就可以防止其对象被拷贝了。其原理是:SpecialClass继承了Uncopyable函数,它的对象如果调用了拷贝构造函数,或者使用了赋值操作符,那么编译时,就会去调用基类的对应函数,但是基类里的这两个函数是private的,所以编译会失败。

另外,boost也提供了一个Uncopyable函数,那个class名字为noncopyable,因此我们也可以这样做:

#include <boost/utility.hpp>

class SpecialClass : boost::noncopyable {

...

};


3. C++0x中的新方法

在C++0x中,新添加了两个关键字:default和delete,可以用于控制某个类使用默认函数(default)或者禁用某个函数(delete)。其中,使用default关键字可以将某个函数定义为默认函数。如:

class SpecialClass {

...

public:

SpecialClass(const SpecialClass&) = default;

SpecialClass& operator=(const SpecialClass&) = default;

};

可能这样写有点多余,但是它可以直观表示“我使用的默认的函数”。而且,如果有人想显式定义默认函数,但是自己写的代码又可能有错误,就可以使用这个关键字,方便且不出错。

delete关键字可以禁用掉类的方法,正如我们上面前两节所做的事情,就可以用这一个关键字完成:

class SpecialClass {

...

public:

SpecialClass(const SpecialClass&) = delete;        //禁用拷贝构造函数

SpecialClass& operator=(const SpecialClass&) = delete;

};

default关键字可以用于一切含有默认方法的函数。delete关键字可以用于类的所有方法,例如可以禁用掉函数的某些类型的参数:

class SpecialClass {

...

public:

void fn(long);

void fn(int) = delete;

};

SpecialClass sc;

long l;

sc.fn(l); //ok, 调用void fn(long);

int i;

sc.fn(i); //error, 调用void fn(int);

上面的代码会将void fn(int)类型的函数禁用掉,而如果不禁用的话,sc.fn(i)会进行隐式转换调用void fn(long)函数。

发布时间: 8年前代码相关122人已围观返回回到顶端

很赞哦! (1)

文章评论

  • 请先说点什么
    热门评论
    121人参与,0条评论

站点信息

  • 建站时间:2016-04-01
  • 文章统计:728条
  • 文章评论:82条
  • QQ群二维码:扫描二维码,互相交流