目录
一、设计一个不能拷贝类
拷贝只会产生在两个场景中:调用拷贝构造函数以及赋值运算符重载,因此想要让一个类禁止拷贝,只需让该类不能调用拷贝构造函数以及赋值运算符重载即可。
- C++98
将拷贝构造函数与赋值运算符重载只声明不定义,并且将其访问权限设置为私有即可。
class CopyBan { // ... private: CopyBan(const CopyBan&); CopyBan& operator=(const CopyBan&); //... };
原因:
1. 设置成私有:如果只声明没有设置成private,用户自己如果在类外定义了,还是能拷贝。
2. 只声明不定义:不定义是因为该函数根本不会调用,定义了其实也没有什么意义,不写反而还简单,而且如果定义了就不会防止成员函数内部拷贝了。
- C++11
C++11扩展delete的用法,delete除了释放new申请的资源外,如果在默认成员函数后跟上=delete,表示让编译器删除掉该默认成员函数。
class CopyBan { // ... CopyBan(const CopyBan&)=delete; CopyBan& operator=(const CopyBan&)=delete; //... };
二、设计一个只能在堆上创建对象的类
方法一:析构函数私有化
那么我们怎么创建对象呢?其实这里不能直接创建对象,只能用指针间接创建一个对象,如下所示。
可以直接用delete吗?
不行,因为delete释放对象的资源会调用对象的析构函数,而析构函数不可访问。这该怎么办呢?
既然析构函数被设置为私有,只能够在类内调用,那我们设置一个public函数调用析构函数可以吗?如下所示:
class HeapOnly
{
public:
void Destroy()
{
this->~HeapOnly();
}
private:
~HeapOnly()
{
cout << "~HeapOnly" << endl;
}
};
//方法一:析构函数私有化
//因为没有析构函数,就只能用new申请资源赋值给类类型的指针。
int main()
{
//HeapOnly hp1;
HeapOnly* hp2 = new HeapOnly;
//delete hp2;
hp2->Destroy();
return 0;
}
运行一下:
调用了析构函数没有问题。
我们还可以用delete调用析构函数,
但这种写法有些繁琐,我们可以将Destroy设置成静态的类成员函数。
这样调用就简单一点。
注意:类的静态成员函数不能使用非静态成员变量,因为使用非静态成员变量要this,而静态成员函数中没有this。上面的静态成员函数调用的变量是ptr,ptr不是成员变量,更不是非静态成员变量,不需要this调用。delete ptr,是delete调用ptr指向空间的析构函数。
方法二:构造函数私有化
因为构造函数私有了,类外部不能直接访问,所以不能直接实例化,也不能通过new赋值给类类型指针了。
同析构函数一样,我们也可以用间接调用构造函数的方式,创造对象指针,如下