随笔 - 576  文章 - 0  评论 - 62  阅读 - 219万

【C++沉思录】代理类

1、考虑下面的需求,把一组类型不同,但是相互关联的对象放入容器中,比如Animal,Dog,Cat对象。
2、容器只能包含一组 类型相同的对象,Animal,Dog,Cat对象是没有办法放入容器中的。
3、怎么解决上面的问题?
假设容器为vector,可以使用vector<Animal>,这会导致一个新问题,因为vector存储的是对象副本,子类放入vector<Animal>发生对象切割,不可能具备多态的性质。

怎么解决上面的问题?
---------------------------------------------------------------------------------------------------------------------
经典的解决办法:
vector中存储Animal指针,这会带来如下问题:
1、Dog d; v.push_back(&d); d是局部对象,离开作用域会自动销毁,容器中的指针指向一堆垃圾。
2、为了解决上面的问题,使用 v.push_back(new Dog(d)); 这会带来动态内存管理的负担,考虑把v[j] 赋值给v[i],
3、v[j] = v[i]; 两个指针指向同一个对象,v[j]和v[i] 不知道彼此,都不释放,内存泄露,都释放,行为未定义。
4、对v[i]做一个副本,由于不知道v[i]的真实类型,使用v[j] = new Animal(v[i]); 这又发生对象切割。
5、解决对象的切割,使用virtual clone方法,如下:v[j] = v[i].clone();

---------------------------------------------------------------------------------------------------------------------
使用代理类,对指针Animal* 封装,栈上对象管理动态内存,实现指针的自动释放。
如下:

复制代码
AnimalProxy::AnimalProxy():_pa(NULL)
{

}

AnimalProxy::~AnimalProxy()
{
delete _pa;
}

// 注意:类中可以访问自己的private成员,也可以访问rhs的private成员
AnimalProxy::AnimalProxy(const AnimalProxy& rhs)
{
_pa = (rhs._pa != NULL ? rhs._pa->Clone():NULL);
}

AnimalProxy& AnimalProxy::operator=(const AnimalProxy& rhs)
{
if(this != &rhs) // 等同测试
{
delete _pa; // delete NULL 也没有问题
_pa = (rhs._pa == NULL ? rhs._pa->Clone():NULL); // 指针为NULL判断
}
return *this; // 返回引用
}

AnimalProxy::AnimalProxy(const Animal& animal):_pa(animal.Clone())
{

}
复制代码

 

posted on   Andy Niu  阅读(337)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示