C++:特殊类设计

C++:特殊类设计 目录1.请设计一个类不能被拷贝2. 只能在堆上创建对象不能在栈上或全局/静态区直接创建对象2.1 方案12.2 方案二3.只能在栈上创建对象4.不能被继承1.请设计一个类不能被拷贝拷贝只会放在两个场景中拷贝构造函数以及赋值运算符重载因此想要让一个类禁止拷贝只需让该类不能调用拷贝构造函数以及赋值运算符重载即可。C98 可将拷贝构造函数与赋值运算符重载只声明不定义并且将其访问权限设置为私有即可。class CopyBan { // ... private: CopyBan(const CopyBan); CopyBan operator(const CopyBan); //... };原因设置成私有如果只声明没有设置成private用户自己如果在类外定义了就可以不能禁止拷贝了只声明不定义不定义是因为该函数根本不会调用定义了其实也没有什么意义不写反而还简单而且如果定义了就不会防止成员函数内部拷贝了。C11扩展delete的用法delete除了释放new申请的资源外如果在默认成员函数后跟上delete表示让编译器删除掉该默认成员函数。class CopyBan { // ... CopyBan(const CopyBan)delete; CopyBan operator(const CopyBan)delete; //... };2. 只能在堆上创建对象不能在栈上或全局/静态区直接创建对象只能在堆上创建对象说明只能通过只指针的方式指向对象在构造和析构函数上做文章。2.1 方案1析构函数私有化然后需要提供 delete 的方法有两种delete方式。class HeapOnly { public: //不加static也行必须实例化p1-Destory1,p1不能为空 //加上static可以实例化调用C 保证 delete nullptr 无操作 static void Destroy1(HeapOnly* ptr) { //合法因为这是在 HeapOnly 的成员函数内部, //可以访问 HeapOnly 的私有成员函数和数据成员,调用 delete 来销毁对象。 delete ptr; } void Destroy2() { delete this; } private: ~HeapOnly() { cout ~HeapOnly endl; } };这样就不能直接创建对象了因为这样必须需要构造函数而new 操作只负责“构造”不负责“析构”。然后可以通过下面三种方式释放空间只能使用一个。类内的 this 就是 ptr 就是指向类的指针。但静态成员函数中不能直接用 this 和 析构因为 this 是一个具体的对象。int main() { //HeapOnly hp1; //static HeapOnly hp2;//执行完都需要 自动 调用析构函数 会出问题不能在栈上或全局/静态区 直接创建对象 HeapOnly* hp3 new HeapOnly; //执行delete 自定义类型会调用析构函数失败 //delete hp3;//不能直接释放因为也要调用析构函数 //也不用再主动 delete 释放了可以调用内部函数完成。 HeapOnly::Destroy1(hp3);//1. 通过静态成员函数来销毁对象成功 hp3-Destroy1(hp3);//2. 通过对象来调用静态成员函数来销毁对象成功 hp3-Destroy2();//3. 通过this指针来销毁对象成功 return 0; }2.2 方案二构造函数私有化那就提供一个 static 构造的方法这里必须加static因为调用成员函数需要现有对象而对象只能通过构造函数但构造函数私有化了先有鸡还是先有蛋问题。拷贝构造 和 operator 也应该禁掉。class HeapOnly { public: //不加static不行因为调用成员函数需要现有对象 //而对象只能通过构造函数但构造函数私有化了 static HeapOnly* CreateObj() { return new HeapOnly; //合法因为这是在 HeapOnly 的成员函数内部, //可以访问 HeapOnly 的私有成员函数和数据成员,调用 new 来创建对象。 } // 禁止拷贝和移动构造防止栈上通过已有对象创建新对象 HeapOnly(const HeapOnly) delete; HeapOnly(HeapOnly) delete;//move()后可以调用 // 禁止拷贝和移动赋值虽不创建新对象但为逻辑完整 HeapOnly operator(const HeapOnly) delete; HeapOnly operator(HeapOnly) delete; private: HeapOnly()//构造函数私有化不能在栈上或全局/静态区 直接创建对象 { } }; int main() { HeapOnly* hp1 HeapOnly::CreateObj(); //合法静态函数才能成功 return 0; }3.只能在栈上创建对象无法 new所以必须构造函数私有然后提供一个 static 的函数来构造。这里是无参的当然也可以传递参数。拷贝构造函数不能禁掉因为要传值返回传不了指针因为函数内部创建的是局部变量如果是创建一个 static 对象那么全局就只有一个 StaticOnly 指针了也不行。class StackOnly { public: static StackOnly CreateObj() { return StackOnly(); } //StackOnly(const StackOnly st) delete;//禁掉后无法 CreateObj 传值返回 void* operator new(size_t size) delete;//相当于间接禁用new。或者设为私有 //当然我们也可以operator 重载new //void* operator new(size_t size) //{ // cout void * operator new(size_t size) endl; // return malloc(size); //} private: StackOnly() {} // 构造函数私有化禁止在堆上创建对象 }; int main() { //因为new必须调用构造函数来创建对象所以当构造函数私有化时无法在堆上创建对象只能在栈上创建对象。 StackOnly obj1 StackOnly::CreateObj(); // 合法通过静态成员函数创建对象 return 0; }new StackOnly(obj1) 执行两步调用 operator new 分配堆内存。operator new是全局的当然这里重载自己的专属operator new不调用全局的。在分配的内存上调用拷贝构造函数用 obj1 作为参数初始化这个新对象。因为拷贝构造函数是 public所以这一步合法。而不使用直接new 调用的才是构造函数StackOnly* obj2 new StackOnly(obj1);4.不能被继承C98方式因为子类构造要调用父类的构造同上将构造函数私有化然后设计静态方法创建对象返回即可。class NonInherit { public: static NonInherit GetInstance() { return NonInherit(); } private: NonInherit() {} };C11方法final关键字final修饰类表示该类不能被继承。class A final { // .... };本篇结束