如何明确的拒绝类对象的复制操作

我们都知道,C++语言的机制会背地里为我们做一些事情。但是有时候我们是不需要有些默认的操作。我们并不想是使用编译器为我们产生的函数,也不想让使用我们所写代码的人使用这些函数。那么,我们应该明确的拒绝(比如我们想禁止某些对象的复制时)。

假设我们想设计一套用于服务学校的缴费系统,那么其中就有学生类:

classCStudent{

public:

    CStudent(std::string name ="",int age =0,int id =0,int nfund =0);

    CStudent(constCStudent& other);

    ~CStudent();

    CStudentoperator=(constCStudent& other);

private:

    std::stringm_sName;

    intm_nAge;

    intm_nStudentID;

    intm_nFund;

};

 

因为每一个学生都是独一无二的,所以在学生类中根本就不需要复制对象操作。因而上述类声明

的拷贝构造函数和赋值函数都变得毫无意义了。那么我们该怎么避免拷贝构造函数和赋值函数呢?

第一种方法:

    通过注释的方式告诉代码使用者:“不能使用拷贝构造函数和赋值函数”。这里虽然是一种方法,但是不能达到“禁止”的目的。

所以最好的方法是在编译的时候就拒绝你的拷贝和复制操作。通常而言,如果你不希望一个类支持某种操作,最简单的方法是什么也不做,因为编译器会对你使用根本没有声明过的函数给出错误提醒。但是对于类的复制操作运算却无能为力,因为编译器不能一方面为你悄悄的声明它们,另一方面却又告诉你它们的声明是无效的,所以这里就产生了矛盾。

那我们应该怎么做来解决这一棘手的问题呢?类的访问控制(Access Control)为我们指明了前进的方向。所有的编译器生成的函数都是public的,如果我们将它们声明为private,一方面阻止了编译器为我们默认声明与定义,另一方面又能禁止对复制操作函数的显示调用。

第二种方法:声明复制操作函数的访问属性为private

    classCStudent{

public:

    CStudent(std::string name ="",int age =0,int id =0,int nfund =0);

    ~CStudent();

private:

    CStudent(constCStudent& other);

    CStudentoperator=(constCStudent& other);

private:

    std::stringm_sName;

    intm_nAge;

    intm_nStudentID;

    intm_nFund;

};

但是这种解决方法还有一点缺陷,如果成员函数和友元函数要对其访问,仍然是畅通无阻的。因为C++的语言机制赋予了它们访问调用private成员函数的权利。不过我们进一步想到了,假如我们只声明不定义,那么成员函数、友元函数对它们的调用就会被编译器明令禁止:“声明而不定义成员函数是合法的,但是使用未定义成员函数的任何行为将导致链接失败!”。这样就实现了类复制操作的完全禁止。

但是,但是!有没有更好的方法呢?上述方法是在链接的时候提示错误,我们是否可以进一步把链接时期错误,提前到编译时期呢?答案是:可以的!

第三种方法:继承自一个禁止复制操作的基类

namespacenoncopyable

{

    classnoncopyable{

    protected:

        noncopyable(){}

        ~noncopyable(){}

    private:

        noncopyable(constnoncopyable&);

        constnoncopyable&operator=(constnoncopyable&);

    };

}

 

classCStudent:publicnoncopyable::noncopyable{

public:

    CStudent(){}

    ~CStudent(){}

};

 

上面我们不需要对学生类声明private的拷贝构造函数和赋值操作符,而是特意声明了一个不可复制的类noncopyable(该类参照boost::noncopyable)。这个基类非常简单,就是把想要禁止的函数声明的访问控制属性为private

为了禁止学生类的拷贝,只要让学生类private的继承noncopyable基类即可。

当调用学生类的拷贝构造函数或者赋值操作符时,编译器使用生成一个拷贝构造函数和一个拷贝赋值操作符,而它调用这些函数时不可避免的调用基类的对应函数,由于在基类中这些操作是 private 的,因此编译器会在编译时期报错。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值