Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/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
Oop Fortran 2003中的类型绑定过程重载_Oop_Fortran_Gfortran_Fortran2003 - Fatal编程技术网

Oop Fortran 2003中的类型绑定过程重载

Oop Fortran 2003中的类型绑定过程重载,oop,fortran,gfortran,fortran2003,Oop,Fortran,Gfortran,Fortran2003,我已经用Java编程好几年了;然而,我现在正在学习一门使用Fortran作为示例代码(77标准)的课程。尽管我一直认为Fortran是一种古老的语言,但我还是决定使用gfortran编译器试用2003标准的最新实现,看看它的优点。到目前为止,我对这些现代功能感到惊讶,但我遇到了一个问题,下面的示例演示了这个问题 module mod1 type type1 real :: x real :: y contains

我已经用Java编程好几年了;然而,我现在正在学习一门使用Fortran作为示例代码(77标准)的课程。尽管我一直认为Fortran是一种古老的语言,但我还是决定使用gfortran编译器试用2003标准的最新实现,看看它的优点。到目前为止,我对这些现代功能感到惊讶,但我遇到了一个问题,下面的示例演示了这个问题

    module mod1
      type type1
        real :: x
        real :: y
        contains
        procedure :: compute
      end type type1
      contains
      subroutine compute(this)
        class(type1) :: this
        this%y = this%x*2 - 1
        write (*,*) this%x,this%y
      end subroutine
    end module mod1

    module mod2
      type type2
        real :: x
        real :: y
        contains
        procedure :: compute
      end type type2 
      contains
      subroutine compute(this)
        class(type2) :: this
        this%y = this%x - 5
        write (*,*) this%x,this%y
      end subroutine
    end module mod2

    program test
      use mod1
      use mod2
      implicit none
      type(type1) myType1
      type(type2) myType2
      myType1%x = 4
      myType2%x = 5
      call myType1%compute
      call myType2%compute
    end program test
这会产生编译错误:“参数‘This’在(1)中的类型不匹配;引用
call myType2%compute
语句将类型(type2)传递给类(type1)”

我的问题是范围问题。似乎通过
class()::这条
语句,编译器应该能够将子例程绑定到特定的派生类型或其后代。从这里开始,编译器在概念上似乎不难搜索一个变量定义,该变量定义从子例程的本地开始,然后向上搜索
this
的特定实例的祖先树。这将消除所有显式
This%
语句,这些语句往往会使我的类型绑定过程在几个语句之后难以阅读。比如说,

    this%tempNew(xI) = this%lamda*this%temp(xI-1)+(1-2*this%lamda)*this%temp(xI)+this%lamda*this%temp(xI+1)
似乎比不上

    tempNew(xI) = lamda*temp(xI-1)+(1-2*lamda)*temp(xI)+lamda*temp(xI+1)
在后一种情况下,通过
class():这条
语句,每个变量都应该绑定,这一点非常明显

另一个结果是,两个独立的派生类型似乎不能具有相同名称的绑定子例程(如错误消息所示)。我看到了两种常见的解决方法。首先是显式调用每个子例程,比如
compute\u type1
compute\u type2
。当访问这些子例程时,这在代码中看起来非常丑陋和冗余。例如
调用myType1%compute\u type1
。第二个选项(参见示例)似乎更好,它是区分绑定名称和过程名称。例如,类型定义将包括
procedure::compute type=>compute\u type1
。这解决了访问子例程时的问题,但我可以看到使用许多实现相同绑定名称的派生类型开发大型项目时的问题。我宁愿不必记录我在任何给定项目中使用过和没有使用过的子例程名称。这往往会使名字很长,最终可读性较差

所以我的问题有三个部分:

  • 对于类型绑定过程中的类成员,是否有比显式键入
    this%
    更干净的替代方法
  • 有没有办法让编译器识别一个过程应该基于
    class()::this
    语句进行绑定?当前重载子例程/函数名的方法似乎是90/95标准的产物,该标准不允许将这些子例程/函数名绑定到类型
  • 如果没有,是否有与此实现相关的性能提升?这两个问题似乎都可以在编译时解决,我很乐意牺牲编译时间来提高表达能力

这更像是一个扩展的注释,但似乎是因为编译器出现故障,您被迫进行推测。我已经用gfortran 4.8.3编译了代码,没有错误,并且得到了预期的结果。而且,在我看来,你想发生的事情应该发生

另一个结果是,两个独立的派生类型似乎不能具有相同名称的绑定子例程(如错误消息所示)

虽然这两个子例程都被称为
compute
,但它们位于单独的模块中,这是允许的,尽管您的
use
语句使得
调用compute(…)
(您没有这样做)不明确。如果类型定义在同一个模块中,那么您必须求助于
procedure::compute=>compute\u typex
技巧,但是
call mytype1%compute
仍然可以接受

我建议,如果您通过类型绑定公开
compute
子例程,那么您可以将它们作为
private
放在模块中,或者至少不要显式地
使用它们。[也就是说,让
仅使用mod1:type1
]

至于您是否在子例程中使用
type%…
,那么是的,我想您是的。也就是说,在Fortran 2008下有
associate
结构

subroutine compute(this)
  class(type1), intent(inout) :: this
  associate (x => this%x, y => this%y)
    ...
  end associate
end subroutine

但在这种情况下,这并没有什么好处。还有其他一些可怕的技巧,我将不详细说明。

您的代码看起来应该满足您的需要。您使用的是哪个gfortran版本?我使用的是用于Linux的gcc版本4.6.3中包含的版本。如果上述代码包含在单个文件test.f03中,并使用
gfortran test.03
编译,请记住在使用gfortran中的-std=f2003标记编译代码时指定标准,否则编译器可能会尝试使用自由格式fortran或其他标准,则会再现错误消息。使用文件扩展名为.f03不能保证编译器遵循的标准实际上是2003,使用4.8版进行编译还允许我删除类型绑定过程中类成员的所有
this%
限定符,而不会出现错误。您偶然发现的原因是您的代码缺少
隐式无
,而不是因为您获得了所需的行为。