gpt4 book ai didi

oop - 如何在子模块 Fortran 中使用类型

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

我有一个基础模块,它定义了一些子例程(sub1sub2sub3)。然后,我想在一系列子模块中覆盖这些子例程。

我知道如何使用单独的模块和延迟类型来做到这一点,但我决定尝试使用子模块。不幸的是,我不明白它们的用法。

这是我目前所拥有的:

基础模块:

module BaseModule
implicit none

interface
subroutine sub1(idx)
implicit none
integer, intent(in) :: idx
end subroutine sub1

subroutine sub2(idx)
implicit none
integer, intent(in) :: idx
end subroutine sub2

subroutine sub3(idx)
implicit none
integer, intent(in) :: idx
end subroutine sub3
end interface
end module BaseModule

ChildModule1:

submodule (BaseModule) ChildModule1
implicit none

type :: Child1
contains
module procedure :: sub1
module procedure :: sub2
end type

contains

module subroutine sub1
print*, "Child 1 - execute 'sub1' - idx = ", idx
end subroutine sub1

module subroutine sub2
print*, "Child 1 - execute 'sub2' - idx = ", idx
end subroutine sub2

end submodule ChildModule1

子模块 2:

submodule (BaseModule) ChildModule2
implicit none

type :: Child2
contains
module procedure :: sub1
module procedure :: sub2
module procedure :: sub3
end type

contains

module subroutine sub1
print*, "Child 2 - execute 'sub1' - idx = ", idx
end subroutine sub1

module subroutine sub2
print*, "Child 2 - execute 'sub2' - idx = ", idx
end subroutine sub2

module subroutine sub3
print*, "Child 2 - execute 'sub3' - idx = ", idx
end subroutine sub3

end submodule ChildModule2

测试:

program test
use ChildModule1
use Childmodule2
implicit none

integer :: idx
type(Child1) :: c1
type(Child2) :: c2

do idx = 1, 10

!! Child1 outputs
call c1%sub1(idx)
call c1%sub2(idx)

!! Child2 outputs
call c1%sub1(idx)
call c2%sub2(idx)
call c1%sub3(idx)
end do

end program test

我对 submodules 的想法是,我不必再次声明所有的 inouts,但是如果我想使用相同的子程序怎么办(例如 sub1) 在我声明不同类型的更多子模块中?现在我得到编译错误:

Error: MODULE PROCEDURE at (1) must be in a generic module interface

最佳答案

我会尝试澄清一些我认为您对 Fortran 中的子模块 机制的误解。

Then, I want to override these subroutines in a series of child modules.

您不会使用子模块覆盖过程,您实现它们。

The idea I get of submodules is that I don't have to declare all the inouts again,

如果 inouts 是指过程的声明和签名(接口(interface)),那么,您不需要(但可以)在子模块中重复它们,但是,这不是子模块的目的。

but what if I want to use the same subroutine (e.g. sub1) within more submodules where I declare different types?

好吧,也许我必须简要解释一下什么是子模块,什么不是。有关详细信息,请参阅@SteveLionel 编写的 this good article,或 Fortran wiki 上的 this entry,或您的 compiler's reference(无论它是什么),甚至是您最喜欢的关于 Modern Fortran 的书。

正如我在 another question 中所说,子模块是一种添加到语言中的功能,用于解决一个特定问题:接口(interface)和实现的分离。主要动机是当您只需要更改模块中的实现细节时生成的编译级联。

子模块可以通过主机关联访问父模块上的实体,但父模块不知道该子模块的存在。当您在子模块 Child1 中声明类型 ChildModule1 时,它只能在此子模块本身内部访问,但不能在父模块 BaseModule 中访问。

此外,ChildModule1 不是模块,并且不能像您在主程序或任何其他程序单元中尝试做的那样是 use d。子模块的唯一作用是实现其父模块中缺少实现的 module procedures

总结:以模块化、合理的方式布置您的源文件和程序单元,并使用子模块如果有意义让您的过程的实现独立于它们的声明(类似于 c头文件和源文件……但对这种比较持保留态度)。


编辑:

我突然想到,您可能认为 Fortran 中的 modulesubmodule 与其他语言中的类和子类相关。 他们没有!也许这是一个普遍的误解,我不知道。

Fortran 有用户定义的类型。它们可以绑定(bind)方法、构造函数和析构函数,可以封装数据,可以扩展,可以动态分派(dispatch),可以声明为抽象,可以延迟和覆盖成员。这相当于其他语言中的类。您可以(这是一种很好的做法)将每种类型和相关内容分离到其对应的模块中。同样,如果需要,您可以为每个扩展类型创建一个模块。

但是,子模块与此无关。

关于oop - 如何在子模块 Fortran 中使用类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55022967/

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