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

Flo*_*nig 1 oop fortran module

我有一个基本模块,其限定某些子程序(sub1sub2sub3)。然后,我想在一系列子模块中覆盖这些子例程。

我知道如何使用单独的模块和延迟类型来执行此操作,但是我决定尝试使用submodules。不幸的是,我不了解它们的用法。

这是我到目前为止的内容:

BaseModule

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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

ChildModule2

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
Run Code Online (Sandbox Code Playgroud)

测试

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
Run Code Online (Sandbox Code Playgroud)

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

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

Rod*_*ues 5

我将尝试消除一些我认为对Fortran 子模块机制有的误解。

然后,我想在一系列子模块中覆盖这些子例程。

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

对子模块的想法是,我不必再次声明所有inout

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

但是,如果我想sub1在声明不同类型的更多子模块中使用相同的子例程(例如),该怎么办?

好吧,也许我必须简要解释一下什么是子模块,什么不是。有关更多详细信息,请参考@SteveLionel撰写的这篇好文章,或参考 Fortran Wiki上的此项,或者参考编译器的引用(无论如何),甚至参考您最喜欢的有关Modern Fortran的书。

就像我在另一个问题中所说的那样,子模块是语言中添加的一项功能,用于解决一个特定的问题:接口和实现的分离。主要动机是当您仅需要更改模块中的实现细节时生成的编译级联。

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

而且,ChildModule1 它不是模块,也不能use像您想做的那样在主程序或任何其他程序单元中被执行。子模块的唯一作用是实现module procedures其父模块中缺少实现的实现。

总结:以模块化,合理的方式布局源文件和程序单元,并在需要使程序实现独立于其声明(类似于c标头和源文件等)的情况下使用子模块。用一粒盐)。


编辑:

我想到您可能正在考虑,module并且submodule在Fortran中与其他语言的类和子类相关。他们不!我不知道这也许是一个普遍的误解。

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

但是,再次,子模块与此无关。