实现
在C++中,类的拷贝:
- 通过拷贝构造函数和赋值构造函数。
- 就是专门为拷贝实现的成员方法。
由于拷贝构造函数和赋值构造函数在用户没有提供的情况下是c++编译器自动生成的,而且是public成员,因此默认的c++类都有拷贝赋值功能
class A {
int val;
};
int main() {
A a;
A b = a;
return 0;
}
如果想要一个C++类不能被拷贝,可以显示的声明类的拷贝构造函数和赋值函数为私有函数,从而达到该类不可被拷贝的目的
- C++11前的noncopyable
#ifndef NOCOPYABLE_H
#define NOCOPYABLE_H
/*
class noncopyable的基本思想是把构造函数和析构函数设置protected权限,这样子类可以调用,但是外面的类不能调用,那么当子类需要定义构造函数的时候不至于通不过编译。但是最关键的是noncopyable把拷贝构造函数和拷贝赋值函数做成了private的,继承自noncopyable的类在执行拷贝操作时会调用基类的拷贝操作,但是基类的拷贝操作是private的,因此无法调用,引发编译错误。
*/
class nocopyable {
protected:
nocopyable(){};
~nocopyable(){};
private: //
nocopyable(const nocopyable& );
nocopyable& operator=(const nocopyable& );
};
#endif //NOCOPYABLE_H
- C++11之后noncopyable
/*
基本思想是: 把构造函数和析构函数设置为protected权限,这样子类可以调用,但是外面的类不能调用。
最关键的是将noncopyable把拷贝构造函数和拷贝赋值函数做成
*/
class noncopyable
{
public: //delete表示禁止类的拷贝赋值操作
noncopyable(const noncopyable&) = delete;
void operator=(const noncopyable&) = delete;
protected: // 可以构造和析构函数
noncopyable() = default;
~noncopyable() = default;
};
怎么使用:只需要继承该类就可以保证派生类不可复制
class A : public nocopyable {};
int main() {
A a1;
A a2 = a1; // 错误:使用了被删除的函数‘A::A(const A&)’
return 0;
}
说明:
- =delete
- 在C++11中,如果想要禁止类的拷贝行为只需要把相应的函数设为 = delete即可 .
- =delete函数,编译器会对指定的函数禁用,从而避免了某些非法的函数调用或者类型转换,从而提高了代码的安全性。
- C++11 标准引入了一个新特性:"=default"函数。程序员只需在函数声明后加上“=default;”,就可将该函数声明为 "=default"函数,编译器将为其自动生成默认的函数定义体,提高代码的执行效率。
测试
class A : private noncopyable
{
public:
A() {}
virtual ~A() {}
protected:
private:
};
class B : public A
{
public:
B() {}
virtual ~B() {}
protected:
private:
};
class C : public B
{
public:
C() {}
~C() {}
protected:
private:
};
int main(int argc, char* argv[])
{
//A a1, a2;
//a2 = a1; //错误:使用了被删除的函数‘A& A::operator=(const A&)’
// B b1, b2(b1); //:使用了被删除的函数‘B::B(const B&)’
// b2 = b2;
//
// C c1, c2;
// c2 = c1;
return 0;
}