我是否需要在主 DLL 代码中显式使用所有模块,
或者“最低”级别的变量和方法是否会被继承
只使用module5和module6?
您不需要需要将模块一直使用到依赖项,只是为了访问实体如果该实体在使用的模块中公开 >.
或者,module5 需要两个 USE 语句(module1 AND module3)还是只需要 module3?
只需使用module5,您就可以访问:
- 在
module5 本身内声明的任何模块实体,标记为public 或protected
-
module5 中由 USE 关联访问的任何实体,标记为 public by module5(实际上,如果未指定,则 public 是默认可访问性)。如果一个实体通过 USE 关联从module1 或module3 访问,但被module5 标记为private,它将无法访问。
我试图在以下示例中涵盖尽可能多的情况。我只使用了变量声明,但同样适用于变量、过程、用户定义类型、运算符、接口......
module module0
! Utiliy module with global constants, could be used at any level.
character(2) :: w = 'w0'
end
module module1
! Low level module. Exposes all the symbols that are not marked as private,
! both defined locally or accessed by use from 'module0'.
use :: module0
private :: z
character(2) :: x1 = 'x1', y1 = 'y1', z = 'z1'
! defined entities: w, x1, y1, z
! public entities : w, x1, y1
end
module module2
! Also low level module, but default access modifier was changed to private,
! so it exposes only symbols marked as public ('z' isn't).
use :: module0
public :: w, x2, y2
private
character(2) :: x2 = 'x2', y2 = 'y2', z = 'z2'
! defined entities: w, x2, y2, z
! public entities : w, x2, y2
end
module module3
! Uses all public names from 'module1' (including 'w' that is from 'module0'),
! but only exposes some of them. Also, defines and exposes local symbols.
use :: module1
private :: x3, y1
character(2) :: x3 = 'x3', y3 = 'y3'
! defined entities: w, x1, y1, x3, y3
! public entities : w, x1, y3
end
module module4
! Here, only selected symbols are accessed from 'module2', and 'w' has been
! renamed into 'w2' to avoid name-conflict with locally defined name 'w'
! (a compile error would had been thrown).
use :: module2, only: w2 => w, x2
public :: w, x2, y4
private
character(2) :: w = 'w4', x4 = 'x4', y4 = 'y4'
! defined entities: w, w2, x2, x4, y4
! public entities : w, x2, y4
end
module module5
! This module can use symbols from lowest level modules that are made public
! by 'module3', without explicitly using those modules.
use :: module3
character(2) :: z = 'z5'
! defined entities: w, x1, y3, z
! public entities : w, x1, y3, z
end
module module6
! As 'y2' is not exposed by 'module4', we could have access to it by using
! 'module2' directly. There is no name-conflict between 'w' from 'module0'
! and from 'module2' because both relate to the same entity. There would be
! conflict with 'w' from 'module4' though, hence the rename.
use :: module0
use :: module2
use :: module4, w4 => w
public :: w, x2, y4, z
private
character(2) :: z = 'z6'
! defined entities: w, w4, x2, y2, y4, z
! public entities : w, x2, y4, z
end
我强烈建议您尽可能尝试使用显式导入,因为它可以使您的代码更清晰并避免名称冲突。作为一般规则,请尝试对模块中的公共实体使用独特的名称,或在 USE 语句中使用重命名子句。
这是前面模块的使用示例:
program main
! There aren't namespaces in Fortran (yet), so attention shall be paid when
! naming symbols meant to be accessed by use association, to avoid conflicts.
! That's why explicit imports are encouraged, as well as implicit none.
use :: module5
use :: module6, z6 => z
implicit none
character(2) :: v = 'v#'
call test_a
call test_b
call test_c
contains
subroutine test_a
! You can access used and defined names in procedures by host association.
print '(5a3)', v, w, x1, y3, z ! output: v# w0 x1 y3 z5
print '(5a3)', v, w, x2, y4, z6 ! output: v# w0 x2 y4 z6
end
subroutine test_b
! Also, you can use modules locally inside procedures. In this case, local
! names "shadow" host associated names, as with 'z' from 'module6' here.
use :: module6
print '(5a3)', v, w, x2, y4, z ! output: v# w0 x2 y4 z6
end
subroutine test_c
! There is no name-conflict error between host and local symbols; the local
! definition (or use association) always "shadows" the host associated name.
use :: module4, only: w
character(2) :: v = 'v_', z = 'z_'
print '(5a3)', v, w, x1, y3, z ! output: v_ w4 x1 y3 z_
end
end
为了完整起见,我要提到Fortran 2018 standard 包含一个名为从模块访问的实体的默认可访问性 的新功能,它允许您将模块名称放入@987654336 @ 或 private 语句,将所述可访问性修饰符应用于该模块中所有使用的实体。
如果模块 a 使用模块 b,则它的实体的默认可访问性
来自 b 的访问是公开的。为每个指定另一个可访问性
实体笨拙且容易出错。现在可以为名称
包含在公开实体名称列表中的模块
或私人的公开或私人声明。这将默认设置为
从该模块访问的所有实体。
我知道今天(2018 年)唯一包含此功能的编译器是 Intel Visual Fortran 19.0。