文章目录
一、请设计一个类,不能被拷贝
类的拷贝只会在两个场景中出现:一个是构造的时候—拷贝构造,另一个则是赋值的时候。
所以只需要将这两种函数禁止用户访问即可。
第一种:私有化
// 将拷贝构造和赋值重载进行私有化,这样用户就访问不到。
class CopyBan
{
private:
int _a;
std::string _b;
private:
CopyBan(const CopyBan&) {}
CopyBan operator=(const CopyBan&) {}
public:
CopyBan(int a = 0, std::string b = "none") {}
};
第二种:禁用delete
// 直接将拷贝构造和赋值重载禁用掉即可。
class CopyBan
{
private:
int _a;
std::string _b;
public:
CopyBan(int a = 0, std::string b = "none") {}
CopyBan(const CopyBan&) = delete;
CopyBan operator=(const CopyBan&) = delete;
};
二、请设计一个类,只能在堆上创建
如果想要用户只能在堆上创建类的话,那就不能让用户直接访问到构造函数和赋值拷贝,因为这种默认的方式都是在栈上创建类对象的。
// 仅提供一个自定义的构造函数,让用户只能通过该接口创建类,这样就能保证只在堆上创建了。
class HeapOnly
{
private:
int _a;
std::string _b;
private:
HeapOnly(int a = 0, std::string b = "none")
:_a(a)
,_b(b)
{}
HeapOnly(const HeapOnly&) = delete;
HeapOnly operator=(const HeapOnly&) = delete;
public:
HeapOnly* HeapCreate(int a = 0, std::string b = "none")
{
HeapOnly* ho = new HeapOnly(a, b);
return ho;
}
};
三、请设计一个类,只能在栈上创建对象
因为只能在栈上创建,所以只需要将new和delete禁用或者私有化即可。
class StackOnly
{
private:
int _a;
std::string _b;
private:
私有化
//void* operator new(size_t) {};
//void operator delete(void*) {};
public:
// 禁用
void* operator new(size_t) = delete;
void operator delete(void*) = delete;
};
四、请设计一个类,不能被继承
如果一个类不能被继承的化,可以用final关键字进行修饰这个类;也可以将该类的构造函数进行私有化,在派生类构造中,钓不到基类的构造,间接的禁止该类被继承。
第一种:私有化
class NoInherit
{
private:
int _a;
std::string _b;
private:
NoInherit(int a = 0, std::string b = "none")
:_a(a)
,_b(b)
{}
public:
static NoInherit Create(int a = 0, std::string b = "none")
{
return NoInherit(a, b);
}
};
第二种:final关键字
class NoInherit final
{
private:
int _a;
std::string _b;
public:
NoInherit() {}
};
五、请设计一个类,只能创建一个对象(单例模式)
单例模式:就是只能创建一个对象。
单例模式分为两种:饿汉模式,懒汉模式。
饿汉模式:
不管将来用不用,程序启动时就创建一个唯一的实例对象。
// 饿汉模式
// 优点:简单
// 缺点:可能会导致进程启动慢,且如果有多个单例类对象实例启动顺序不确定。
class EagerInitialization
{
private:
// 声明一个静态的对象
static EagerInitialization _instance;
private:
// 构造函数私有化
EagerInitialization()
{
std::cout << "Singleton instance created" << std::endl;
}
public:
// 返回实例
static EagerInitialization* GetInstance()
{
return &_instance;
}
// 禁用拷贝构造和赋值重载
EagerInitialization(const EagerInitialization&) = delete;
EagerInitialization& operator=(const EagerInitialization&) = delete;
};
// 定义一个静态对象
EagerInitialization EagerInitialization::_instance;
懒汉模式:
延迟加载,当需要用到时,才创建对象。
不支持线程安全:
class LazyInitialization
{
private:
// 声明静态对象
static LazyInitialization* _instance;
// 构造函数私有化
LazyInitialization() {}
public:
// 延迟加载,得到_instance
LazyInitialization* GetInstance()
{
if (_instance == nullptr)
{
_instance = new LazyInitialization();
}
return _instance;
}
// 禁用拷贝构造和赋值重载
LazyInitialization(const LazyInitialization&) = delete;
LazyInitialization& operator=(const LazyInitialization&) = delete;
};
// 初始化对象
LazyInitialization* LazyInitialization:: _instance = nullptr;
支持线程安全:
// 支持线程安全
class LazyInitialization
{
private:
// 声明静态对象和锁
static LazyInitialization* _instance;
static std::mutex mtx;
// 构造函数私有化
LazyInitialization() {}
public:
// 延迟加载,得到_instance
LazyInitialization* GetInstance()
{
if (_instance == nullptr)
{
// 自动加锁解锁,保证开辟空间的操作是原子的
std::lock_guard<std::mutex> lg(mtx);
if (_instance == nullptr)
_instance = new LazyInitialization();
}
return _instance;
}
// 禁用拷贝构造和赋值重载
LazyInitialization(const LazyInitialization&) = delete;
LazyInitialization& operator=(const LazyInitialization&) = delete;
};
// 初始化对象和锁
LazyInitialization* LazyInitialization:: _instance = nullptr;
std::mutex LazyInitialization::mtx;
谢谢大家!