个人主页:Lei宝啊
愿所有美好如期而遇
不能被拷贝的类
这里我们介绍两种方式,使得一个类不能被拷贝
C++98---私有拷贝构造函数
class BanCopy_98
{
public:
BanCopy_98() = default;
private:
BanCopy_98(const BanCopy_98& copy);
int _a;
};
这样,在类外,就无法对这个类的对象进行拷贝构造了。
C++11---delete删除拷贝构造
class BanCopy_11
{
public:
BanCopy_11() = default;
BanCopy_11(const BanCopy_11& copy) = delete;
private:
int _a;
};
这个就比较彻底,不仅在类外无法拷贝构造,类内也不可以。
只能在堆上创建的类
私有构造函数
class HeapOnly
{
public:
template<class ...Args>
static HeapOnly* Create(Args ...args)
{
return new HeapOnly(args...);
}
void Destroy()
{
delete this;
}
~HeapOnly() { cout << "~HeapOnly" << endl; }
private:
//构造私有,防止栈上创建对象
HeapOnly(){}
HeapOnly(int a, int b)
:_a(a)
,_b(b)
{}
//拷贝构造私有防止这种情况,HeapOnly ho2(*ho1);
HeapOnly(const HeapOnly & ho){}
int _a;
int _b;
};
私有析构函数
class HeapOnly
{
public:
HeapOnly() {}
HeapOnly(int a, int b)
:_a(a)
,_b(b)
{}
template<class ...Args>
static HeapOnly* Create(Args ...args)
{
return new HeapOnly(args...);
}
void Destroy()
{
delete this;
}
private:
//拷贝构造私有防止这种情况,HeapOnly ho2(*ho1); 拷贝就在堆上深拷贝
HeapOnly(const HeapOnly& ho) {}
~HeapOnly() { cout << "~HeapOnly" << endl; }
int _a;
int _b;
};
因为如果在栈上创建对象,这个对象在类外会自动调用析构函数,而析构函数是私有的,所以这样也就防止了对象在栈上创建。
只能在栈上创建的类
class StackOnly
{
public:
StackOnly() {}
StackOnly(int a, int b)
:_a(a)
,_b(b)
{}
template<class ...Args>
static StackOnly Create(Args ...args)
{
return StackOnly(args...);
}
//无法防止,于是可以这样:StackOnly* ho1 = new StackOnly(ho);
StackOnly(const StackOnly& ho) {}
//new先调用operator new,然后才会调用构造。
//这个operator new是我们重载的,所以new这个对象时优先调用我们这里的。
void* operator new(size_t) = delete;
~StackOnly() { cout << "~StackOnly" << endl; }
private:
int _a;
int _b;
};
要创建只能在栈上创建的类,如果我们私有了构造,调用Create方法,那么返回这样一个对象需要拷贝构造,而一但需要拷贝构造,就会出现在堆上也能拷贝构造的情况.
如果我们不私有构造,那么堆上也就可以构造了,所以我们考虑ban掉operator new,new分为两个步骤,先调用operator new,然后才会调用对象的构造,所以我们在这个对象中重载一个类专属的operator new,这样在动态创建一个对象时,调用new时就会使用这个类中我们重载的operator new。
而我们只要ban掉operator new,构造和拷贝构造不私有也是没问题的。
不能被继承的类
C++98---私有基类构造函数
class Base_98
{
public:
private:
Base_98() {}
protected:
int _a;
};
C++11---final关键字
//C++11新增final关键字,修饰类,则类不可被继承,修饰虚函数,则虚函数不可被重写
class Base final
{
public:
Base(){}
private:
int _a;
};
单例对象类
什么叫单例对象,意思是在一个进程中,只存在一个这样的对象。
饿汉单例对象类
class hunger
{
public:
static hunger* hungerCreate()
{
return &hg;
}
bool set() {} //赋值
bool add() {} //新增
bool mod() {} //修改
hunger(const hunger&) = delete;
hunger& operator=(const hunger&) = delete;
~hunger() { cout << "~hunger" << endl; }
private:
hunger() { cout << "hunger create" << endl; }
int _a;
int _b;
vector<string> vs;
static hunger hg;
};
hunger hunger::hg;
但是饿汉有一个缺点就是,这个对象会在main函数前就创建,而main函数前没有多线程,于是如果这个对象初始化的数据很多,就会迟迟进不了main函数,无法执行我们的逻辑。
懒汉单例对象类
我们这里实现的懒汉,不允许外界释放资源,由我们内部定义的gc对象释放。
class lazy
{
public:
static lazy* lazyCreate()
{
if (hg == nullptr)
{
hg = new lazy;
}
return hg;
}
bool set(){} //赋值
bool add(){} //新增
bool mod(){} //修改
lazy(const lazy&) = delete;
lazy& operator=(const lazy&) = delete;
void del()
{
delete hg;
//delete this;
hg = nullptr;
}
private:
lazy() { cout << "lazy create" << endl; }
~lazy() { cout << "~lazy" << endl; }
int _a;
int _b;
vector<string> vs;
static lazy* hg;
class gc
{
public:
~gc()
{
hg->del();
}
};
static gc auto_del_lazy;
};
//类型(需要类域) + 变量名(需要类域)
lazy* lazy::hg = nullptr;
lazy::gc lazy::auto_del_lazy;
这里的懒汉其实可以更加简单点,比如这样做:
class lazy
{
public:
static lazy* lazyCreate()
{
static lazy lz;
return &lz;
}
bool set() {} //赋值
bool add() {} //新增
bool mod() {} //修改
lazy(const lazy&) = delete;
lazy& operator=(const lazy&) = delete;
private:
lazy() { cout << "lazy create" << endl; }
~lazy() { cout << "~lazy" << endl; }
int _a;
int _b;
vector<string> vs;
};
懒汉的目的就是在进入main函数后再初始化这个单例对象,这样即使它的数据量很大,但是进入main中,因为我们有了多线程,也就是卡一个线程,其他的线程不受影响,逻辑还可以继续执行下去。