2

在我看来,子模块的一个很好的特性是您可以在子模块中创建一个辅助函数,而程序员的成本很低;您不会触发编译级联,不会弄乱命名空间或文档,并且可以立即清楚地知道该函数在哪里可以使用和不能使用。它们就像更好的private函数版本。

但是,子模块中的函数不能是used。虽然这按预期工作,但似乎这也阻止了该功能进行单元测试。我知道的两个单元测试框架pFUnitfruit都需要use语法才能运行。

对于如何访问 fortran 模块中的私有变量private?,但是这些解决方案似乎都不适用于子模块中的函数,至少在没有否定将这些函数放在子模块中的所有好处的情况下。

那么这个问题有什么解决方案吗?

4

2 回答 2

2

引入这个submodule概念的主要目的是避免在模块文件中只引入一个小的非接口破坏更改时,长时间的重新编译级联。这是通过分离过程的接口并将它们放在父模块中并将实现保留在子模块中来完成的。

子模块本身可以有子模块,这对于非常大的程序很有用。我见过的子模块的层级数一般不超过两级(即一个模块有子模块,本身有子模块)但没有限制。每个模块或子模块都是树的根,其其他节点是它的后代,并且可以通过主机关联访问它。没有其他子模块有这样的访问权限,这有助于独立开发大型模块的一部分。此外,没有任何机制可以从其他地方访问子模块中声明的任何内容——正如您所说,它实际上是私有的。

因此,综上所述,如果您需要来自任何级别的任何子模块的任何内容以供程序的任何其他部分访问,则必须在子模块的原始父模块中声明它。据我所知,没有其他方法可以访问原始父模块中未给出接口或声明的任何子模块中的任何内容。

一旦您将过程接口和变量/类型声明放在父模块中,您就可以use在程序中的任何位置使用它们,即使过程实现可能隐藏在父模块的子模块中。

于 2021-02-26T20:27:31.823 回答
1

我对子模块几乎没有经验(所以不确定这是否有用),但只是为了扩展我上面的评论......

!! parent_mod.f90 (public things)
module parent_mod
    implicit none

    type myint_t
        integer :: n = 100
    contains
        procedure :: add, show
    endtype

    interface
        module subroutine add( x )
            class(myint_t) :: x
        end
        module subroutine show( x )
            class(myint_t) :: x
        end
    endinterface
end

!! parent_helper.f90 (private things to be used by parent_impl.f90
!! and possibly by unit tests)
module parent_helper
    use parent_mod, only: myint_t
    implicit none
contains
    subroutine debug_show( x )
        type(myint_t) :: x
        print *, "debug: x = ", x
    end
end

!! parent_impl.f90  (implementation)
submodule (parent_mod) parent_impl
    implicit none
contains
    module procedure add
        x% n = x% n + 1
    end
    module procedure show
        use parent_helper, only: debug_show
        call debug_show( x )
    end
end

!! main.f90
program main
    use parent_mod, only: myint_t
    implicit none
    type(myint_t) :: a

    call a% add()
    call a% show()  !! 101

    call a% add()
    call a% show()  !! 102

    block
      use parent_helper
      call debug_show( a )  !! 102
    endblock
end

!! build
$ gfortran-10 -fcheck=all -Wall -Wextra parent_mod.f90 parent_helper.f90 parent_impl.f90 main.f90

这是否可能有助于避免重新编译 parent_mod.f90(即使 parent_helper 或 parent_impl 被修改)?(而且我注意到模块名称“parent”在这里没有意义...... XD)

于 2021-02-28T20:57:31.967 回答