1. 设计一个类,不能被拷贝
如果一个类不能被拷贝,那么只需要让类外面不能调用类的拷贝构造和赋值重载即可
1. C++98的实现方式
将类的构造函数和赋值重载只声明不实现,并且声明为private的
因为不声明的编译器会默认生成public的拷贝构造和赋值重载,因此需要声明为private的
//设计一个类不能被拷贝 class NoCopy { public: NoCopy() {} private: NoCopy(const NoCopy& obj); NoCopy& operator=(const NoCopy& obj); }; void test1() { NoCopy obj1; NoCopy obj2(obj1); }
2. C++11的实现方式
C++11提供了新的关键字delete,用于表示禁用某个函数,那么此时我们只需要禁用拷贝构造和赋值重载即可
class NoCopy { public: NoCopy() {} NoCopy(const NoCopy& obj) = delete; NoCopy& operator=(const NoCopy& obj) = delete; private: }; void test1() { NoCopy obj1; NoCopy obj2(obj1); }
2. 设计一个类,只能在堆上创建对象
要规定某个类的创建位置,那么自动生成的构造函数就不能再使用了,而是重新提供一个方法,用于创建对象,在这个方法内部进行一些限制即可为了保证这个类创建的对象全部都在堆上,所以需要将所有的构造函数全部封起来,然后重新提供一个函数用来创建对象即可
//设计一个只能在堆上创建对象的类 class HeapOnly { public: HeapOnly* CreateObj() { return new HeapOnly; } private: HeapOnly() {} };
但是这样会有一个问题:我们要怎么调用这个CreateObj函数呢?
这是一个先有鸡还是先有蛋的问题:我们得通过对象来调用类的成员函数,但是这里需要先调用成员函数来创建对象,所以这里要给
CreateObj
函数使用static修饰,让其可以通过类名访问(HeapOnly::CreateObj()
)
同时,我们还需要将拷贝构造给私有化,否则将会出现HeapOnly obj2 = *pobj;
的情况,会构造一个obj2是在栈上的
所以最终的设计代码为:
//设计一个只能在堆上创建对象的类 class HeapOnly { public: static HeapOnly* CreateObj() { return new HeapOnly; } private: HeapOnly() {} HeapOnly(const HeapOnly& obj) {}; }; void test() { HeapOnly* pobj = HeapOnly::CreateObj(); HeapOnly obj2 = *pobj; }
当然,在C++11之后,我们可以使用delete关键字禁用拷贝构造函数
3. 设计一个类,只能在栈上创建对象
同样的,需要将默认构造函数私有化,然后重新提供一个方法,用于创建对象,在这个方法内部进行一些限制
//设计一个只能在栈上创建对象的类 class StackOnly { public: static StackOnly CreateObj() { return StackOnly(); } private: StackOnly() {} }; void test() { StackOnly obj1 = StackOnly::CreateObj(); }
这里能够禁用掉在堆上创建对象的方式,但是没有办法完全禁掉其他方式,这里可以使用static
修饰对象,让其在静态区创建static StackOnly obj1 = StackOnly::CreateObj();
如果想禁止在静态区创建的话,这里可以考虑禁止拷贝构造
但是禁止了拷贝构造之后就不能使用
StackOnly obj1 = StackOnly::CreateObj();
这种方式调用构造对象了,因此,这个类我们是封不死的,最多只能限制不这样使用
4. 设计一个类不能被继承
4.1C++98的方式
构造函数私有化,所有派生类在构造对象的时候都会自动调用基类的构造函数,基类的构造函数被私有化之后派生类构造对象的时候无法自动调用。
class NonInherit { public: static NonInherit CreateObj() { return NonInherit(); } private: NonInherit() {} }; class Derive : NonInherit { public: private: int a; }; void test1() { Derive De; }
4.2 C++11之后的方式
C++11新增了final关键字,final修饰类,表示该类不能被继承
class NonInherit final { }; class Derive : NonInherit { public: private: int a; };