Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Fortran:从函数的返回类型访问值_Fortran_Operator Overloading - Fatal编程技术网

Fortran:从函数的返回类型访问值

Fortran:从函数的返回类型访问值,fortran,operator-overloading,Fortran,Operator Overloading,我已经创建了一个派生类型V,并包含了一个add函数 这样我就可以使用运算符+ 但是当我这样做的时候 z = u + v Call vsum(z, u, v) 不执行该操作。我想这是因为z%kn 未被访问 但是当我这样做的时候 z = u + v Call vsum(z, u, v) 一切正常 下面是派生类型和 重载函数vadd Module vtest Type :: V Character (Len=8) :: kn Real, Allocatable :: vc(:

我已经创建了一个派生类型V,并包含了一个add函数 这样我就可以使用运算符+

但是当我这样做的时候

z = u + v
Call vsum(z, u, v) 
不执行该操作。我想这是因为
z%kn
未被访问

但是当我这样做的时候

z = u + v
Call vsum(z, u, v) 
一切正常

下面是派生类型和 重载函数vadd

Module vtest

Type :: V

  Character (Len=8) :: kn
  Real,  Allocatable :: vc(:)

  Contains

    Procedure :: vadd
    Generic :: Operator (+) => vadd

 End Type vtest

Contains

Function vadd (b, c) Result (a)
  Type (V) :: a
  Class (V), Intent (In) :: b, c

  !!$ In vsum, use is made of a% kn 
  Call vsum (a, b, c)

End Function vadd

 Subroutine vsum (ta, tb, tc)
   Type (V), Intent (InOut)  :: ta
   Type (V), Intent (In) :: tb, tc

   Logical :: la, lb, lc

   la = .False.;  lb = .False.;  lc = .False.

   Select Case (ta%kn) 

   Case ("Real32")
     If (Allocated (ta%vc)) la = .True.
     If (Allocated (tb%vc)) lb = .True.
     If (Allocated (tc%vc)) lc = .True.
     If (la .And. lb .And. lc) Then 
       ta%vc = tb%vc + tc%vc
     End If

   End Select

 End Subroutine vsum

End Module vtest


Program test
Use vtest
Type (V) :: z

   z% kn = "Real32"
   Allocate (z% vc_real32(3))
   Write (*,*) "z = u + v"
   Write (*,*) "z% kn: ", z% kn
   z = u + v
   Write (*,*) "z% kn: ", z% kn
   Write (*,*) "z: ", z% vc_real32

End Program vtest

让我们看看子程序
vsum
。在该子例程中完成的工作取决于所有三个对象的组件定义
ta
tb
tc
。为使求和按预期进行,必须分配所有可分配组件,并使
ta%kn
'Real32'
匹配

没有完整的工作示例,但正如您所说,当有一个像

call vsum(z, u, w)  ! V is the name of the type, so call the variable w
z%kn
设置为
'Real32'

但是,使用定义的操作

z = u + w
有一个函数引用

z = vadd(u, w)
电话在哪

call vsum (a, b, c)  ! Actual arguments "z", u, w.
现在,
a
vadd
的函数结果。这样做的结果是,就像带有
intent(out)
a
的伪参数一样,最初是未定义的


这基本上意味着,当通过
vadd
z
时,它将使用未定义的组件
kn
和未分配的组件
vc
到达
vsum
。因此,总和的要求没有得到满足(事实上,
select case
构成了无效的引用)


我想我也可以评论一下如何解决这个问题

vsum
中,实际上是从“结果”中获取操作类型。相反,类似于

Subroutine vsum (ta, tb, tc)
  Type (V), Intent (Out)  :: ta
  Type (V), Intent (In) :: tb, tc

  Logical :: lb, lc

  lb = .False.;  lc = .False.

  ! In here we probably want some consistency checking...
  Select Case (tb%kn)    
  Case ("Real32")
    If (Allocated (tb%vc)) lb = .True.
    If (Allocated (tc%vc)) lc = .True.
    If (lb .And. lc) Then 
      ta%vc = tb%vc + tc%vc   ! ta%vc being automatically allocated
    End If
  End Select

 End Subroutine vsum
当然,这并不能满足您(从标题中)从结果中获取操作类型的愿望。您可以使用原始的子例程方法来实现这一点,但有一种情况除外,那不是Fortran函数的原理

如果要使用已定义的操作,则不能在赋值的左侧定义该操作。在表达式
u+w
中,没有左侧,但定义的操作仍应正常运行。也就是说,在声明中

z = u + w

您不是说“
z
是应用于
u
w
的操作的结果”。但是:“计算应用于
u
w
的操作
+
,并将结果(通过定义或隐式赋值)分配给
z
”。在到达“结果类型”之前,存在该赋值。这就是为什么我在前面将
z
作为实际参数放在引号中的原因。

请显示
vsum
的代码。代码仍然不完整。几乎没有一个mcve它缺少操作符调用及其周围环境。在您未显示的任何细节中都可能存在错误。您应该准备一个完全可编译的代码。包括代码的输出。您是如何诊断未执行该操作的?发生了什么,而不是?+1,尤其是最后一段。Fortran函数从不“查看”作业左侧的内容。他们根本不需要被安排在任务中!它们计算了一些表达式,而调用代码不知怎么地使用了该表达式。这意味着,本质上,当通过vadd z时,它将使用未定义的组件kn和未分配的组件vc传递给vsum。因此,总和的要求没有得到满足(事实上,select案例构成了一个无效的引用)这就是正在发生的事情。我已经尝试了你的修改,但是我仍然没有得到正确返回的结果。在函数“vadd”中调用“vsum”后打印了数组值,得到了正确的值。但是,在主程序中,输出的结果仍然未定义。您的意思是,在调用
vadd
之后,
a
具有正确的值,但这些值随后不会传递到
z
?这对我来说没有多大意义,但我确实看到您的主程序并不完全正确:右侧变量没有定义(其中一个仍然命名不正确)。