1.请设计一个类,不能被拷贝
拷贝构造函数以及赋值运算符重载,因此想要让一个类禁止拷贝,只需让该类不能调用拷贝构造函数以及赋值运算符重载即可。
//该类不能发生拷贝
class NonCopy
{
public:
NonCopy(const NonCopy& Nc) = delete;
NonCopy& operator=(const NonCopy& Nc) = delete;
};
2.请设计一个类,只能在堆上创建对象
实现方式:
1. 将类的构造函数私有,拷贝构造声明成私有。防止别人调用拷贝在栈上生成对象。然后提供一个静态的成员函数,在该静态成员函数中完成堆对象的创建。
2.将类的析构函数私有,然后提供一个公有的Delete函数提供释放资源的功能。
//只能在堆上创建对象
class OnlyHeap
{
public:
OnlyHeap()
:_a(0)
{}
void Delete()
{
delete this;
}
private:
~OnlyHeap()
{}
private:
int _a;
};
3. 请设计一个类,只能在栈上创建对象
思路:同上将构造函数私有化,然后设计静态方法创建对象返回即可。
//只能在栈上创建对象
class OnlyStack
{
public:
static OnlyStack GetInstance()
{
OnlyStack st;
return st;
}
void* operator new(size_t n) = delete;
private:
OnlyStack()
:_a(0)
{}
private:
int _a;
};
4. 请设计一个类,不能被继承
//该类不能被继承
class NonInheritable final
{};
final关键字,final修饰类,表示该类不能被继承。
5.单例模式
一个类只能创建一个对象,即单例模式,该模式可以保证系统中该类只有一个实例,并提供一个
访问它的全局访问点,该实例被所有程序模块共享。
单例模式有两种实现模式:
- 饿汉模式
就是说不管你将来用不用,程序启动时就创建一个唯一的实例对象。
// 饿汉模式 -- 一开始(main函数之前)就创建出对象
// 优点:简单、没有线程安全问题
// 缺点:
// 1、一个程序中,多个单例,并且有先后创建初始化顺序要求时,饿汉无法控制。
// 比如程序两个单例类A 和 B,假设要求A先创建初始化,B再创建初始化。
// 2、饿汉单例类,初始化时任务多,会影响程序启动速度。
class MemoryPool
{
public:
static MemoryPool* GetInstance()
{
return _a;
}
private:
MemoryPool()
{}
mutex mtx;
static MemoryPool* _a;
};
MemoryPool* MemoryPool::_a = new MemoryPool;
-
懒汉模式
如果单例对象构造十分耗时或者占用很多资源,这种情况使用懒汉模式(延迟加载)更好。
/ 懒汉模式:第一次使用对象再创建实例对象
// 优点:
// 1、控制顺序。
// 2、不影响启动速度。
// 缺点:
// 1、相对复杂。(线程安全问题)
// 2、线程安全问题要处理好
class Singleton
{
public:
static Singleton* GetInstance()
{
if (_a == nullptr)//提高效率
{
_mtx.lock();
if (_a == nullptr)//保护多线程
{
_a = new Singleton;
}
_mtx.unlock();
}
return _a;
}
static void Delete()
{
_mtx.lock();
if (_a)
{
delete _a;
_a = nullptr;
}
_mtx.unlock();
}
class GC
{
public:
~GC()
{
Delete();
}
};
// 定义一个静态成员变量,程序结束时,系统会自动调用它的析构函数从而释放单例对象
static GC _gc;
private:
Singleton()
{}
private:
static mutex _mtx;
static Singleton* _a;
};
Singleton* Singleton::_a = nullptr;
mutex Singleton::_mtx;
Singleton::GC Singleton::_gc;
}