一、请设计一个不能被拷贝的类:只需让该类不能调用拷贝构造函数以及赋值运算符重载即可。
实现方式:
1.设置成私有(private)。
2.只声明不定义:如果定义了成员函数可能会内部拷贝。(C++98)
//C++98
class CopyBan
{
private:
CopyBan(const CopyBan&);
CopyBan& operator=(const CopyBan&);
};
3.在默认成员函数后跟上=delete,表示让编译器删除掉该默认成员函数。(C++11)
//C++11
class CopyBan
{
CopyBan(const CopyBan&)=delete;
CopyBan& operator=(const CopyBan&)=delete;
};
二、请设计一个类,只能在堆上创建对象:
实现方式:
1. 将类的构造函数私有,拷贝构造声明成私有。防止别人调用拷贝在栈上生成对象。
2. 提供一个静态的成员函数,在该静态成员函数中完成堆对象的创建。
class HeapOnly
{
public:
static HeapOnly* CreateObject()
{
return new HeapOnly;
}
private:
HeapOnly() {};
// C++98
HeapOnly(const HeapOnly&);
C++11
HeapOnly(const HeapOnly&) = delete;
};
3.将类的析构函数私有。
4.提供一个成员函数,在该成员函数中完成堆对象的清理释放。
class HeapOnly
{
public:
void Destroy()
{
delete this;
}
private:
~HeapOnly()
{}
};
三、请设计一个类,只能在栈上创建对象:
堆:不仅能通过构造创建对象,还能通过拷贝构造创建对象,故
1.同上将构造函数私有化,(但是不能将拷贝构造私有化,因为栈的传值返回需要调用拷贝构造)。
2.因为new相当于operator new+构造函数,所以可以重载该类专属的operator new。
3.然后设计静态方法创建对象返回即可。
class StackOnly
{
public:
static StackOnly CreateObj()
{
return StackOnly();
}
// 禁掉operator new可以把下面用new调用拷贝构造申请对象给禁掉
void* operator new(size_t size) = delete;
void operator delete(void* p) = delete;
private:
StackOnly()
:_a(0)
{}
private:
int _a;
};
四、请设计一个类,不能被继承
1、构造函数私有化,派生类中调不到基类的构造函数,则无法继承。(C++98)
//C++98
class NonInherit
{
public:
static NonInherit GetInstance()
{
return NonInherit();
}
private:
NonInherit()
{}
};
2、fifinal修饰类,表示该类不能被继承。(C++11)
//C++11
class A final
{};
五、请设计一个类,只能创建一个对象(单例模式):一个类只能创建一个对象,即单例模式,该模式可以保证系统中该类只有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享。
1、饿汉模式:程序启动时就创建一个唯一的实例对象。
①如果单例对象初始化内容很多,影响启动速度。
②如果两个单例类,互相有依赖关系,无法保证初始化的先后顺序。
2、创建步骤:
①构造函数私有化,在该类中声明,在类外定义一个自己类型的静态对象(不要直接定义一个该类的全局对象,因为类外面是调不了构造函数的)。
②提供获取单例对象的接口函数。
③防拷贝。
//饿汉模式
namespace hungry
{
class Singleton
{
public:
// 2、提供获取单例对象的接口函数
static Singleton& GetInstance()
{
return _sinst;
}
private:
// 1、构造函数私有
Singleton()
{}
// 3、防拷贝
Singleton(const Singleton& s) = delete;
Singleton& operator=(const Singleton& s) = delete;
static Singleton _sinst;
};
Singleton Singleton::_sinst;
};
2、懒汉模式:延迟加载。
1、优点:第一次使用实例对象时,创建对象。进程启动无负载。多个单例实例启动顺序自由控
制。
2、创建步骤:
①构造函数私有化,在该类中声明,在类外定义一个自己类型的静态对象指针并置空。
②提供获取单例对象的接口函数(第一次调用GetInstance的时候创建单例对象)。
③防拷贝。
④提供一个可以显示调用析构函数的函数(智能指针无法支持对象显示释放)。
⑤定义一个内部类GC,在类中定义一个静态的_gc对象,销毁后自动调用析构。
namespace lazy
{
class Singleton
{
public:
// 2、提供获取单例对象的接口函数
static Singleton& GetInstance()
{
if (_psinst == nullptr)
{
// 第一次调用GetInstance的时候创建单例对象
_psinst = new Singleton;
}
return *_psinst;
}
//4、提供一个可以显示调用析构函数的函数
//一般单例不用释放
//特殊场景:1、中途需要显示释放 2、程序结束时,需要做一些特殊动作(如持久化)
static void DelInstance()
{
if (_psinst)
{
delete _psinst;
_psinst = nullptr;
}
}
//5、定义一个内部类GC,在类中定义一个静态的_gc对象,销毁后自动调用析构。
class GC
{
public:
~GC()
{
lazy::Singleton::DelInstance();
}
};
private:
// 1、构造函数私有
Singleton()
{}
~Singleton()
{};
// 3、防拷贝
Singleton(const Singleton& s) = delete;
Singleton& operator=(const Singleton& s) = delete;
static Singleton* _psinst;
static GC _gc;
};
Singleton* Singleton::_psinst = nullptr;
Singleton::GC Singleton::_gc;
}