特殊类的设计

设计一个不能被拷贝的类

​ 拷贝只会放生在两个场景中:拷贝构造函数以及赋值运算符重载,因此想要让一个类禁止拷贝, 只需让该类不能调用拷贝构造函数以及赋值运算符重载即可。

  • C++98

    将拷贝构造函数与赋值运算符重载只声明不定义,并且将其访问权限设置为私有即可。

    class CopyBan
    {
        // ...
        private:
        CopyBan(const CopyBan&);
        CopyBan& operator=(const CopyBan&);
        //...
    };
    

    设置成私有:如果只声明没有设置成private,用户自己如果在类外定义了,就可以不 能禁止拷贝了 只声明不定义:不定义是因为该函数根本不会调用,定义了其实也没有什么意义,不写 反而还简单,而且如果定义了就不会防止成员函数内部拷贝了。

  • C++11

    C++11扩展delete的用法,delete除了释放new申请的资源外,如果在默认成员函数后跟上 =delete,表示让编译器删除掉该默认成员函数。

    class CopyBan
    {
        // ...
        CopyBan(const CopyBan&)=delete;
        CopyBan& operator=(const CopyBan&)=delete;
        //...
    };
    

设计一个只能在堆创造对象的类

#include <iostream>
class HeapOnly
{
public:
    static HeapOnly* CreatObj()//然后再写一个函数用于创建堆上的对象
    {
        return new HeapOnly;
    }
    //要加上静态!如果没有静态我们就必须先创建对象然后才能调用函数!
    //但是我们又智能允许才堆上创建对象!必须构造私有化!
    //有了静态后我们就可以直接用类调用函数了·
private:
    HeapOnly()//首先构造函数私有化
    {}
    //拷贝构造也要私有
    HeapOnly(const HeapOnly& hp) = delete;

};

int main()
{
    //我们首先要封了构造函数!
    //不然我们可以随意的在栈/堆/静态区上创建对象!
    //HeapOnly hp1;
    //HeapOnly* hp2 = new HeapOnly;
    //static HeapOnly hp3;

    HeapOnly* hp4 = HeapOnly::CreatObj();
    //如果不私有化拷贝构造
    //就可以怎么写
    //HeapOnly hp5(*hp4);
    return 0;
}

​ 实现方式:

  1. 将类的构造函数私有,拷贝构造声明成私有。防止别人调用拷贝在栈上生成对象。

  2. 提供一个静态的成员函数,在该静态成员函数中完成堆对象的创建

另一种思路就是封掉析构函数!这样子出了作用域之后就没有办法调用析构函数了!

但是这时候就没法delete了!我们只能在类里面写一个函数用来释放!

#include <iostream>
class HeapOnly
{
public:
       void destroyObj()
       {
           this->~HeapOnly();//要加上this不然会报错!
       }
private:
       ~HeapOnly()//首先析构私有化
       {}
       HeapOnly(const HeapOnly& hp) = delete;
   
};

int main()
{
       HeapOnly* hp = new HeapOnly;
       hp->destroyObj();
       return 0;
}

设计一个只能在栈上创建的类

class StackOnly
{
public:
       static StackOnly CreatObj()
       {
           return StackOnly();
       }
    
       void print()
       {
           cout << "hello";
       }
       //void* operator new(size_t) = delete;
       //void operator delete(void*) = delete;
       //可以禁掉new和delete!
       //但是只能禁掉new出来的对象!无法禁掉static创建的对象!
private:
       StackOnly()//构造函数私有化
       {}
       //拷贝构造不用私有化,因为栈上的对象不会调用拷贝构造
};

int main()
{
       StackOnly st = StackOnly::CreatObj();
       //StackOnly* st2 = new StackOnly;
       //static Static so2;//只有封掉构造函数才能将静态区的封掉
       //但是这个类是封不死的!
       //如果不封掉拷贝构造那么下面这种也就没法封死!而且会导致st也无法创建!
       static StackOnly st1 = StackOnly::CreatObj();
    
       //如果封掉了拷贝构造我们只能怎么使用
       StackOnly::CreatObj().print();
       //我们不去直接的接收对象!
       //或者直接使用引用接收
       const StackOnly& so4 = CreatObj();
       return 0;
}

设计一个无法被继承的类

  • C++98
//构造私有化
class NonInherit
{
public:
       static NonInherit GetInstance()
       {
           return NonInherit();
       }
private:
       NonInherit()
       {}
};
  • C++11

final关键字,final修饰类,表示该类不能被继承。

class A  final
{
    // ....
};