论坛
潜水/灌水快乐,沉淀知识,认识更多同行。
ToB圈子
加入IT圈,遇到更多同好之人。
朋友圈
看朋友圈动态,了解ToB世界。
ToB门户
了解全球最新的ToB事件
博客
Blog
排行榜
Ranklist
文库
业界最专业的IT文库,上传资料也可以赚钱
下载
分享
Share
导读
Guide
相册
Album
记录
Doing
应用中心
搜索
本版
文章
帖子
ToB圈子
用户
免费入驻
产品入驻
解决方案入驻
公司入驻
案例入驻
登录
·
注册
只需一步,快速开始
账号登录
立即注册
找回密码
用户名
Email
自动登录
找回密码
密码
登录
立即注册
首页
找靠谱产品
找解决方案
找靠谱公司
找案例
找对的人
专家智库
悬赏任务
圈子
SAAS
IT评测·应用市场-qidao123.com技术社区
»
论坛
›
数据库
›
Oracle
›
C++特殊类设计(不能被拷贝的类、只能在堆上创建对象的 ...
C++特殊类设计(不能被拷贝的类、只能在堆上创建对象的类、不能被继承的类 ...
渣渣兔
论坛元老
|
2024-11-24 07:03:38
|
显示全部楼层
|
阅读模式
楼主
主题
1589
|
帖子
1589
|
积分
4767
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要
登录
才可以下载或查看,没有账号?
立即注册
x
C++特殊类设计
在实际应用中,可能必要设计一些特殊的类对象,如
不能被拷贝的类、只能在堆上创建对象的类、只能在栈上创建对象的类、不能被继承的类、只能创建一个对象的类(单例模式)
。
1. 不能被拷贝的类
拷贝只会发生在两个场景中:拷贝构造函数和赋值运算符重载。因此,
让一个类禁止被拷贝,只必要让其拷贝构造函数和赋值运算符重载不能被调用即可
。
1.1 c++98做法
c++98通过将拷贝构造函数和赋值运算符重载
只声明不界说,并将其访问权限设置为私有
实现禁止被拷贝。
class CopyBan
{
private:
CopyBan(const CopyBan& cb);
CopyBan& operator=(const CopyBan & cb);
};
复制代码
1.2 现代做法
利用c++11提供的delete关键字“删除”拷贝构造函数和赋值运算符重载。
class CopyBan
{
private:
CopyBan(const CopyBan& cb) = delete;
CopyBan& operator=(const CopyBan& cb) = delete;
};
复制代码
2. 只能在堆上创建对象的类
2.1 直接法
要使一个类只能在堆上创建对象,思路是:
将类的构造函数和拷贝构造函数私有,防止别人调用拷贝在栈上生成对象。
再提供一个静态成员函数,在该静态成员函数内部完成堆对象的创建。
class HeapOnly
{
static HeapOnly* Create()//静态解决“先有函数还是现有对象问题”
{
return new HeapOnly;
}
private:
HeapOnly(){}
};
复制代码
但此不能完全封死在栈上创建对象,如果通过 Create()函数先创建一个堆上的对象,再利用默认拷贝构造拷贝堆上的对象,就能够实现在栈上创建对象。
HeapOnly* ho1 = HeapOnly::Create();
HeapOnly* ho2(ho1);
复制代码
以是末了还必要封死通过拷贝构造创建栈上对象:
c++98:private:HeapOnly& HeapOnly(const HeapOnly& ho){}
c++11:HeapOnly& HeapOnly(const HeapOnly& ho)=delete;
2.2 私有析构函数法
设计不能被拷贝的类还有一种方法,通过
私有化析构函数
,让栈上对象无法在脱离作用域时自动调用析构函数,因此在栈上的创建对象的代码都不能被编译通过。再设计一个 release()函数
手动释放堆上的对象
。
class HeapOnly
{
public:
static HeapOnly* Create()
{
return new HeapOnly;
}
void relase()
{
delete this;
}
private:
~HeapOnly(){}
};
复制代码
3. 只能在栈上创建对象的类
要使一个类只能在栈上创建对象,思路是:
私有化构造函数
设计静态函数返回对象
class StackOnly
{
public:
static StackOnly Create()
{
return StackOnly();
}
void* operator new(size_t size) = delete;
void operator delete(void* p) = delete;
private:
StackOnly():_a(0){}
int _a;
};
复制代码
设计只能在栈上创建对象的类还要注意将new和delete删除,避免利用new通过拷贝构造创建堆上对象。且由于 Create()函数被设计成传值返回,不能直接通过删除拷贝构造实现(因为临时对象)。
删除new和delete的原理是,编译器默认生成一个new和一个delete,现将重载new和delete在类中重载,那么类对象会调用重载的new和重载的delete(重载后不再默认生成),但由于重载的new和重载的delete被删除,类对象在创建时便无法利用。
StackOnly so1 = StackOnly::Create();
StackOnly* so2 = new StackOnly(so1);
复制代码
4. 不能被继承的类
要使一个类不能被继承,方法是:
c++98:基类析构函数私有,派生类不能调用基类的构造函数,无法编译通过
c++11:利用final关键字标记基类,表现该类不能被继承
5. 单例模式
单例模式要求一个类只能创建一个对象,该模式可以抱枕系统中该类只有一个实例,并提供一个访问它的全局访问点,该实例被所有步伐模块共享。
单例模式有两种实现模式:
饿汉模式
懒汉模式
5.1 饿汉模式
饿汉形容步伐对对象的必要比较紧急,不管将来用不消,
在步伐启动时就马上先创建一个唯一的实例对象
(一般在main函数之前创建)。
#include<iostream>
using namespace std;
class ehan
{
public:
static ehan* GetInstance()
{
return &_e;
}
int SetInfo(int info)
{
_info = info;
return _info;
}
ehan(const ehan& e) = delete;
ehan& operator=(const ehan& e) = delete;
private:
ehan(){}
int _info;
static ehan _e;//声明
};
ehan ehan::_e;//定义
int main()
{
cout<<ehan::GetInstance()->SetInfo(1);
return 0;
}
复制代码
优先:简单
缺点:可能会导致进程启动慢,且如果有多个单例类利用饿汉模式,它们的对象实例启动顺序不确定
5.2 懒汉模式
懒汉模式可以完美解决饿汉模式的缺点,懒汉模式一般在第一次调用 GetInstance() 的时间创建单例对象。
#include<iostream>
using namespace std;
class lanhan
{
public:
static lanhan* GetInstance()
{
static lanhan _lh;
return &_lh;
}
int SetInfo(int info)
{
_info = info;
return _info;
}
lanhan(const lanhan& e) = delete;
lanhan& operator=(const lanhan& e) = delete;
private:
lanhan(){}
int _info;
};
int main()
{
cout<<lanhan::GetInstance()->SetInfo(1);
return 0;
}
复制代码
这里在 GetInstance()里 界说了一个局部静态对象 static lanhan _lh; ,即使调用多次 GetInstance(),这个创建对象的代码也只会实行一次,但这种利用方法是
c++11之后支持,且有线程安全风险
。
传统且线程安全方法:
#include<iostream>
#include<mutex>
using namespace std;
class lanhan
{
public:
static lanhan* GetInstance()
{
if (_lh == nullptr)//双重检查保证线程安全
{
unique_lock<mutex> lock(_mtx);
if (_lh == nullptr)
{
_lh = new lanhan;
}
}
return _lh;
}
int SetInfo(int info)
{
_info = info;
return _info;
}
lanhan(const lanhan& e) = delete;
lanhan& operator=(const lanhan& e) = delete;
private:
lanhan(){}
int _info;
static mutex _mtx;
static lanhan* _lh;
};
lanhan* lanhan::_lh = nullptr;
mutex lanhan::_mtx;
int main()
{
cout<<lanhan::GetInstance()->SetInfo(1);
return 0;
}
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复
使用道具
举报
0 个回复
倒序浏览
返回列表
快速回复
高级模式
B
Color
Image
Link
Quote
Code
Smilies
您需要登录后才可以回帖
登录
or
立即注册
本版积分规则
发表回复
回帖并转播
回帖后跳转到最后一页
发新帖
回复
渣渣兔
论坛元老
这个人很懒什么都没写!
楼主热帖
SqlServer2012升级到SqlServer2016
事务的ACID特性
深度干货!一篇Paper带您读懂HTAP | St ...
DCM: 中间件家族迎来新成员
SaaS软件工程师成长路径
iOS事件传递链与响应链
(内附源码)Node.js小试——使用Node ...
arthas使用介绍
.NET for Apache Spark 入门演练
Java后端05(初识MyBatis)
标签云
集成商
AI
运维
CIO
存储
服务器
登录参与点评抽奖加入IT实名职场社区
下次自动登录
忘记密码?点此找回!
登陆
新用户注册
用其它账号登录:
关闭
快速回复
返回顶部
返回列表