2

我有这三个功能:

当我运行前 2 个函数时,没有问题,但是当我运行最后一个函数 (LMTD) 时,它显示“除以零”,但当我调试一些参数时,有些参数有值,有些没有。我知道我必须做什么,但我想知道为什么我必须这样做,因为这对我来说毫无意义。

Tinn-function 没有 Tut 的参数,所以我必须将它们添加到 Tinn-function 的参数中。Tut 也是如此,它不知道 Tinn 的所有论点,而 LMTD 必须同时拥有 Tinn 和 Tut 的论点。如果我这样做,一切都会顺利进行。为什么我必须这样做?

Public Function Tinn(Tw, Qw, Qp, Q, deltaT)

Tinn = (((Tw * Qw) + (Tut(Q, fd, mix) * Q)) / Qp) + deltaT

End Function

Public Function Tut(Q, fd, mix)

Tut = Tinn(Tw, Qw, Qp, Q, deltaT) _
    - (avgittEffektAiUiLMTD() / ((Q * fd * mix) / 3600))

End Function

Public Function LMTD(Tsjo)

LMTD = ((Tinn(Tw, Qw, Qp, Q, deltaT) - Tsjo) - (Tut(Q, fd, mix) - Tsjo)) _
    / (WorksheetFunction.Ln((Tinn(Tw, Qw, Qp, Q, deltaT) - Tsjo) _
       / (Tut(Q, fd, mix) - Tsjo)))

End Function
4

1 回答 1

5

我将尝试对如何传递参数进行有用且完整的解释:

据我所知,LMTD 是调用另一个函数的主要函数。每次调用一个新函数时,它都会被放置在他们所谓的“堆栈”之上;
Stack的原理涉及在内存的一端(栈顶)分配和释放内存:内存被分配给在栈顶的函数中声明和使用的那些局部变量(被调用的函数在作用域内)并在堆栈顶部形成一个新层),而一旦函数超出范围(返回值时),这些局部变量就会被释放。通常称为“后进先出”(LIFO)的东西。
因此,如果您将 LMTD 视为基础(它可能不是最终基础,因为它必须由另一个子例程或函数调用),只要调用这些函数,Tinn 和 Tut 就会放在堆栈顶部。

但是(这就是重点),
不在函数中本地声明并作为参数传递的变量是通过引用传递的标准,它们是指针变量,包含由底层函数(或子)发送的参数的内存地址堆。当函数通过引用(默认)获取参数时,它可以更改传递的内存地址所包含的值,因此在返回被调用函数时可以更改原始变量值。

这个例子说明了这一点:

Sub Base_Sub()

Dim i as single
Dim c as single
Dim d as single

c = 5
d = 6

i = Function_1(c, d)

End Sub

Function Function_1(c, d)

c = 7 'Notice that the variables c and d are also changed in the Base_sub
d = 5 

Function_1 = c + d

End Function

相反,如果您按值发送变量(byVal 关键字),这将意味着制作原始变量(作为参数传递)的副本,并且在函数中操作副本时原始变量保持不变. 换句话说,这个副本将成为堆栈顶部的局部变量,并在函数超出范围时立即释放。

因此,无需深入研究您的代码,当您在一个例程中调用许多函数时,它可能会帮助您牢记不同层的这一一般概念。为了密切关注您的局部变量,请使用 VBA 中的“locals”窗口进行跟进或使用 debug.print 在即时窗口中进行跟进。可以通过执行检查来帮助您获得更多关于错误的透明度。例如对于 Tinn 函数:

If QP = 0 then 
    'Notify problem at QP. 
end if

如果我的解释超出了您的预期,我很抱歉,但我试图在这一点上尽可能完整。

于 2012-07-05T09:14:05.943 回答