1

我定义了一个类CellArrayHandle,它的唯一属性是函数句柄的元胞数组:

classdef CellArrayHandle < handle    
    properties
        cel  % cell array of function handles    
    end 
end

假设myHandle是 CellArrayHandle 的一个对象因此myHandle.cel是一个 n×1 函数句柄元胞数组,即myHandle.cel{i}是 i = 1 到 n 的函数句柄。

我想做一些更新(例如 i=1),但以下不起作用:

  myHandle.cel{1} = @(x) myHandle.cel{1}(x) + 0.5;

Matlab说“达到500的最大递归限制”,所以它似乎被理解为无限递归。然而,以下工作:

  f = @(x) f(x) + 0.5;

对于函数句柄 f。

似乎当我将函数句柄作为属性封装到类中时,上面的更新方法将不起作用。

我不明白前者和后者之间的区别。有人可以在这一点上帮助我吗?非常感谢。

此致,

坦率

4

1 回答 1

2

差异源于句柄类的语义

您可以将句柄对象分配给多个变量或将其传递给函数,而不会导致 MATLAB 复制原始对象。

或者,借用Highlander的原始想法,当您实例化一个句柄类时,“只能有一个”(内存中的实例的全局,您将其分配给它的所有变量只创建引用而不是新副本)。

考虑示例脚本:

f = @(x) x;
f = @(x) f(x) + 0.25;
f = @(x) f(x) + 0.50;

b = CellArrayHandle();
b.cel{1} = @(x) x;
b.cel{1} = @(x) b.cel{1}(x) + 0.25;
b.cel{1} = @(x) b.cel{1}(x) + 0.5;

fval = f(1);
bval = b.cel{1}(1);

如果我调试这个脚本并在fval评估之前查看堆栈,我会看到:

K>> dbstack
> In @(x)x
  In @(x)f(x)+0.25
  In @(x)f(x)+0.5

因此 Matlab 能够在f创建后续f句柄的过程中创建当前函数句柄的副本,并且可以形成堆栈。

当我对 做同样的事情时b,我得到了这个:

K>> dbstack
> In @(x)b.cel{1}(x)+0.5
  In @(x)b.cel{1}(x)+0.5
  In @(x)b.cel{1}(x)+0.5
  In @(x)b.cel{1}(x)+0.5
  In @(x)b.cel{1}(x)+0.5
  In @(x)b.cel{1}(x)+0.5
  ...

发生这种情况是因为对 的属性的每次赋值都会生成该值b的属性,而无需创建类的新实例。所以赋值本质上是无限递归的。b

您可以通过不让类继承自(默认)handle而是从value(默认)继承来解决此问题。通过从< handle中删除classdef,并重复dbstack句柄调用,我们有

K>> dbstack
> In @(x)x
  In @(x)b.cel{1}(x)+0.25
  In @(x)b.cel{1}(x)+0.5

发生这种情况是因为对 now 属性的每次赋值b都会复制 current b,实例化一个 new b,并将旧定义 存储b在函数句柄中以形成正确的堆栈。

于 2015-04-21T11:17:15.267 回答