句柄类(handle class)(一)

问题:对于某些类来说,能够避免复制其对象是很有好处的。因为有可能对象太大,复制起来消耗太大。也有可能每个对象代表一种不能被轻易复制的资源,譬如文件等等情况。需要有一种方法,让我们在避免某些缺点(缺乏安全性)的同时能够获取指针的某些优点。尤其是在保持多态性的前提下,避免复制对象的代价,因此我们引入句柄类来解决这一问题。

以一个简单的类作为例子。


关于这个类有必要做三点说明

1.如果使用 Point(int x = 0, int y = 0): xval(x), yval(y) {}

来代替上述的两个构造函数,毫无疑问,可以只需给出x的值便可以构造一个Point对象。而这样做几乎可以肯定是错的。因为一个点不可能只通过x的值就能确定。

2.重载了x和y成员函数

3.之所以将修改类的对象的成员函数的返回值设置为Point&,是因为这样做便可以连续调用该函数以修改对象。如果P是Point的一个对象,那么便可以使用P.x(2).y(2)的形式修改对象。

接下来我们要考虑的是如何将Point对象绑定到句柄。

之所以使用句柄,原因之一是为了避免不必要的对象复制。也就是说得允许多个句柄绑定到单个对象上。将handle类直接绑定到对象P上,那么handle最好与P的内存分配和释放无关。考虑这样的情况,Handle h(P);如果这样直接绑定,一旦P被删除,Handle会怎样呢?显然,删除P之后应该使Handle无效,那么Handle如何知道P被删除了呢?或者说,应该同时删除Handle吗?如果P是一个局部变量,那么P就会被删除两次,Handle离开时一次,P超出自己作用域一次。

因此,handle应该“控制”它所绑定的到的对象,也就是说handle应该创建和销毁对象。有两种可能的选择:

1.Handle h0(123, 456)即把用于创建Point的参数传给这个handle。

2.Handle h(p) 即创建自己的Point对象并把它赋给一个handle去进行复制。

简单的实现:


引用计数型句柄

我们必须了解有多少个句柄绑定在同一对象上,只有这样才能确定应当在何时删除对象。借鉴智能指针tr1::shared_ptr的工作机制,我们使用引用计数来达到这个目的。当然这个引用计数不能是句柄的一部分。我们必须重新定义一个类来容纳一个引用计数和一个Point对象。这个类纯粹是为了实现而设计的。


到这我们可以回到Handle类,来完成成员函数的设计。


接下来我们再考虑最后一个问题,我们的句柄是需要值语义还是指针语义。看下面的例子

Handle h(3,4);

Handle h2 = h;

h2.x(5);

int n = h.x();

如果希望句柄为值语义,则在这个例子中,我们希望n等于3。即绑定到同一对象的句柄互不影响。如果采用指针语义则是相反的情况。因此有以下两种实现方式。

指针语义:

值语义:

需要注意的是,原来Handle的引用计数可能不为1,所以需要保证新的Handle引用计数为1。这就意味着我们需要在UPoint这个类中添加一个私有成员函数,来设置引用计数。

上面的代码运用了一种叫做写时复制(copy on write),其优点是只有在绝对必要时才进行复制,从而避免了不必要的复制,而且额外开销也只有一点点。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
`classdef Observe < handle` 是一个MATLAB中的定义语句,表示定义了一个名为Observe的,该继承自MATLAB内置的handle。 具体来说,这个语句定义了一个可以被观察的对象,该对象包含了一个观察者列表。当对象发生变化时,会通知所有的观察者进行相应的处理。 继承自handle,具有MATLAB对象的句柄特性,可以通过引用来传递和修改对象,而不是通过复制对象来传递和修改。这样可以提高程序的效率和灵活性。 在Observe中,可以定义一些方法来添加、删除和通知观察者,以及一些属性来表示对象的状态。例如,可以定义一个`addObserver`方法来添加观察者,一个`removeObserver`方法来删除观察者,一个`notifyObservers`方法来通知观察者对象的变化,以及一个`status`属性来表示对象的状态。 以下是一个简单的Observe的示例代码: ``` classdef Observe < handle properties status % 对象状态 end properties (Access = private) observers = {} % 观察者列表 end methods function addObserver(obj, observer) % 添加观察者 obj.observers{end+1} = observer; end function removeObserver(obj, observer) % 删除观察者 idx = find(cellfun(@(x)isequal(x,observer), obj.observers)); obj.observers(idx) = []; end function notifyObservers(obj) % 通知观察者 for i = 1:length(obj.observers) obj.observers{i}.update(obj); end end end methods (Abstract) update(obj) % 抽象方法,观察者需要实现该方法 end end ``` 在这个示例中,Observe定义了一个抽象方法`update`,表示观察者需要实现该方法来响应对象的变化。在添加、删除和通知观察者的方法中,使用了MATLAB内置的cell数组来存储观察者对象,使用了`cellfun`函数来查找和删除观察者对象。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值