gpt4 book ai didi

oop - Fortran 2003 中的类型绑定(bind)过程重载

转载 作者:行者123 更新时间:2023-12-05 01:05:32 26 4
gpt4 key购买 nike

我已经用 Java 编程了几年了。但是,我现在正在学习使用 Fortran 作为示例代码(77 标准)的类(class)。尽管我一直将 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

这会产生编译错误:“(1) 处的参数 'this' 中的类型不匹配;将 TYPE(type2) 传递给 CLASS(type1)”引用 call myType2%compute陈述。

我的问题是范围。看来,通过 class(<class_name>) :: this语句,编译器应该能够将子例程绑定(bind)到特定的派生类型或其后代。从这里开始,编译器在子例程中从本地开始搜索变量定义,然后在 this 的特定实例的祖先树上继续搜索,这在概念上似乎并不困难。 .这将消除所有显式 this%在几条语句之后往往会使我的类型绑定(bind)过程难以阅读的语句。例如,
    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(<class_name>) :: this 是相当明显的。语句,每个变量都应该被绑定(bind)。

另一个后果是,两个独立的派生类型似乎不能绑定(bind)同名的子例程(如错误消息所示)。我已经看到了两种常见的方法。首先是显式调用每个子程序,例如 compute_type1compute_type2 .当访问这些子程序时,这在代码中看起来非常丑陋和冗余。例如 call myType1%compute_type1 .第二个选项(参见例如 Overloaded fortran interface with different ranksType-bound function overloading in Fortran 2003 )似乎更好,是区分绑定(bind)名称和过程名称。例如,类型定义将包括 procedure :: compute type => compute_type1 .这解决了访问子例程时的问题,但是在开发具有许多实现相同绑定(bind)名称的派生类型的大型项目时,我可以看到问题。我宁愿不必跟踪我在任何给定项目中拥有和未使用的子例程名称。这会使名称最终变得很长且可读性降低。

所以我的问题有3个组成部分:
  • this%<var_name> 的显式类型是否有更简洁的替代方法?对于类型绑定(bind)过程中的类成员?
  • 有什么方法可以让编译器认识到应该根据 class(<class_name>) :: this 绑定(bind)一个过程?陈述?当前重载子例程/函数名称的方法似乎是 90/95 标准的产物,该标准不允许将它们绑定(bind)到类型。
  • 如果没有,是否有与此实现相关的一些性能提升?这两个问题似乎都可以在编译时解决,我很乐意为提高表达能力做出牺牲。
  • 最佳答案

    这更像是一个扩展评论,但由于编译器失败,您似乎被迫推测。我已经用 gfortran 4.8.3 编译了代码,没有错误,并且得到了预期的结果。另外,在我看来,你想要发生的事情应该发生。

    The other consequence is that it appears that two separate derived types cannot have bound subroutines of the same name (as shown by the error message).



    虽然这两个子程序都被称为 compute它们位于不同的模块中,这是允许的,尽管您的 use声明使 call compute(...) (你没有这样做)模棱两可。如果类型定义在同一个模块中,那么您将不得不求助于 procedure :: compute => compute_typex诡计,但是 call mytype1%compute还是可以接受的。

    如果您要公开 compute,我建议您这样做。通过类型绑定(bind)的子例程,然后您将它们作为 private在模块中,或者至少不要明确地 use他们。 [即有 use mod1, only : type1 .]

    至于你是否卡在 type%...在子程序中,那么是的,我认为你是。也就是说,在 Fortran 2008 下有 associate构造
    subroutine compute(this)
    class(type1), intent(inout) :: this
    associate (x => this%x, y => this%y)
    ...
    end associate
    end subroutine

    但在这种情况下并没有太大的收获。还有其他可怕的技巧我不会详细说明。

    关于oop - Fortran 2003 中的类型绑定(bind)过程重载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21343488/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com