gpt4 book ai didi

interface - Fortran 的 "abstract"和 "normal"接口(interface)之间的区别

转载 作者:行者123 更新时间:2023-12-04 14:56:49 26 4
gpt4 key购买 nike

我试图了解抽象接口(interface)和“普通”接口(interface)之间的区别。是什么让接口(interface)抽象?什么时候需要每一个?

假设下面的例子

module abstract_type_mod
implicit none

type, abstract :: abstract_t
contains
procedure(abstract_foo), pass, deferred :: Foo
end type

interface
subroutine abstract_foo ( this, a, b )
import :: abstract_t
implicit none
class(abstract_t), intent(in) :: this
real, intent(in) :: a
real, intent(out) :: b
end subroutine
end interface

end module

module concrete_type_mod
use abstract_type_mod
implicit none

type, extends ( abstract_t ) :: concrete_t
contains
procedure, pass :: Foo
end type

contains

subroutine Foo ( this, a, b )
implicit none
class(concrete_t), intent(in) :: this
real, intent(in) :: a
real, intent(out) :: b

b = 2 * a

end subroutine
end module

module ifaces_mod
implicit none

interface
subroutine foo_sub ( a, b )
implicit none
real, intent(in) :: a
real, intent(out) :: b
end subroutine
end interface

end module

module subs_mod
implicit none

contains

pure subroutine module_foo ( a, b )
implicit none
real, intent(in) :: a
real, intent(out) :: b

b = 2 * a

end subroutine

end module

program test
use ifaces_mod
use subs_mod
use concrete_type_mod
implicit none

type(concrete_t) :: concrete
procedure(foo_sub) :: external_sub
procedure(foo_sub), pointer :: foo_ptr
real :: b

foo_ptr => external_sub

call foo_ptr ( 0.0, b )
print*, b

foo_ptr => module_foo

call foo_ptr ( 1.0, b )
print*, b

call concrete%Foo ( 1.0, b )
print*, b

end program

pure subroutine external_sub ( a, b )
implicit none
real, intent(in) :: a
real, intent(out) :: b

b = a + 5

end subroutine

输出是
5.000000
2.000000
2.000000

我在这里没有使用抽象接口(interface)。至少我认为我没有?我已经这样做了一段时间,而且我从未在接口(interface)上使用过抽象的“限定符”。看来我还没有发现需要使用抽象接口(interface)的情况。

有人可以在这里启发我吗?

PS:编译器 Intel Visual Fortran Composer XE 2013 SP1 更新 3。

编辑:

引用现代 Fortran 中的 Metcalf、Reid 和 Cohen 的解释:

In Fortran 95, to declare a dummy or external procedure with an explicit interface, one needs to use an interface block. This is fine for a single procedure, but is somewhat verbose for declaring several procedures that have the same interface (apart from the procedure names). Furthermore, in Fortran 2003, there are several situations where this becomes impossible (procedure pointer components or abstract-type bound procedures).



那么,我的编译器是否错误地接受了下面的代码以及上面具有抽象类型的代码?
module ifaces_mod
implicit none

interface
subroutine foo_sub ( a, b )
implicit none
real, intent(in) :: a
real, intent(out) :: b
end subroutine
end interface

end module

module my_type_mod
use ifaces_mod
implicit none

type my_type_t
procedure(foo_sub), nopass, pointer :: Foo => null()
end type

end module

在这两种情况下,我都会说我实际上已经声明了抽象接口(interface)而没有使用 abstract 关键字。我认为我的困惑源于编译器接受这样的代码这一事实。

最佳答案

“正常”接口(interface) - 被标准称为特定接口(interface) block (正如您在问题标题中使用的那样) - 只是某些过程的正常接口(interface) block 。所以:

interface
subroutine foo_sub
end subroutine
end interface
表示存在一个名为 foo_sub 的实际(外部)子例程并且符合指定的接口(interface)。
抽象接口(interface)
abstract interface
subroutine foo_sub_abs
end subroutine
end interface
只是指定某些过程的外观,但名称是接口(interface)的名称,而不是任何实际过程的名称。它可以用于过程指针
procedure(foo_sub_abs), pointer :: p
或用于虚拟参数
subroutine bar(f)
procedure(foo_sub_abs) :: f
这意味着 p 的实际程序将指向或作为 f 传递符合抽象接口(interface)。
请注意,在前两个示例中,您可以使用一些现有过程而不是抽象接口(interface)。它只需要在范围内具有可用的显式接口(interface)(通常它在同一个模块中,或者在使用的模块中)。

据我所知(但请参阅下面的@IanH 评论)编译器可以拒绝您的代码:
  interface
subroutine abstract_foo ( this, a, b )
import :: abstract_t
implicit none
class(abstract_t), intent(in) :: this
real, intent(in) :: a
real, intent(out) :: b
end subroutine
end interface
因为不存在名为 abstract_foo 的实际过程.一些编译器不会对此进行诊断,但他们可以。

完全不相关的是通用接口(interface)。您可以识别它们,因为在单词 interface 之后有一个通用过程的名称。
  interface generic_sub
procedure sub1

subroutine sub2(...)
end subroutine
end interface
这里 sub1sub2两者都存在, sub1已知并且已经有明确的接口(interface)可用, sub2是外部的,看起来与接口(interface)指定的一样,都是通用 generic_sub 的特定过程.这是完全不同的用法。
然后你打电话
call generic_sub(...)
并根据您传递的参数,编译器选择调用哪个特定过程,如果是 sub1 , 或 sub2 .
我要强调的是,这些可以拆分为在不同位置声明的具有相同名称的独立接口(interface) block 。您可以通过这种方式将特定过程添加到现有的通用过程中。

关于interface - Fortran 的 "abstract"和 "normal"接口(interface)之间的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35068442/

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