我注意到父模块使用的(子)模块中的变量只能通过父模块在主程序中访问。这是一个概念,它明确区分了Fortran中的use
语句和C / C ++中的include
语句。以下程序清楚地说明了这一概念。
a.f90
module a_mod
use b_mod
implicit none
integer :: a
end module
b.f90
module b_mod
use c_mod
implicit none
integer :: b
end module
c.f90
module c_mod
implicit none
integer :: c = 10
contains
subroutine inc_c
c = c + 10
end subroutine inc_c
end module
test.f90
program test
use a_mod
implicit none
call inc_c
write(*,*),c
end program
请注意,我只需使用c_mod
就可以在a_mod
中调用一个函数。请注意,除非我遍历依赖项列表,否则我无法直接观察到c_mod
可用。
但是在复杂的软件中,如果变量可用于特定的行,是否有一种简单的方法可以知道(例如,使用IDE)?
答案 0 :(得分:2)
在我看来,最好的办法是避免使用一揽子<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.0.0</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>com.mycompany.clinikeymaven.App</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.0</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
</build>
语句,特别是对于大型且有时笨重的模块。而是通过use
关键字指定要继承的模块实体,例如:
only
这很有效,但令人困惑,因为program main
use a_mod, only : c, inc_c
implicit none
call inc_c
write(*,*) c
end program main
不是a_mod
和c
的真正所有者。因此,您应该尝试inc_c
实际声明它们的实体,这样做:
use
现在,任何阅读代码的人都清楚地知道哪些变量和子程序在范围内以及它们来自何处。
最后,这有一个额外的好处,即降低使用program main
use c_mod, only : c, inc_c
! ^ This has changed
implicit none
call inc_c
write(*,*) c
end program main
的风险,而不会意识到它实际上来自c
。不使用c_mod
!
答案 1 :(得分:1)
正如Vladimir F在评论中建议的那样,您可以使用模块中的private
和public
语句来解决此问题。如果你重写这样的模块:
module a_mod
use :: b_mod
private
public :: a
integer :: a
end module
module b_mod
use :: c_mod
private
public :: b
integer :: b
end module
module c_mod
private
public :: c, inc_c
integer :: c = 10
contains
subroutine inc_c
c = c + 10
end subroutine
end module
在这种情况下,每个模块开头的语句private
表示模块中声明的数量默认情况下不导出。现在,您必须通过添加use
语句,在public
模块时显式声明要使哪些变量和子例程可用。 (也可以使用语法integer, public :: c = 10
在一行中完成。)这种做法可以防止c_mod
变量泄漏出b_mod
,依此类推。
答案 2 :(得分:0)
虽然不像IDE一样有效,但gfortran可以通过附加-fdump-fortran-original
(或-fdump-parse-tree
)选项打印导入符号列表。为此,我们首先生成* .mod文件为
gfortran -c {c,b,a}.f90
并将所需的源编译为
gfortran -fdump-fortran-original -c test.f90
然后,我们得到一个导入符号列表,如下所示:
Namespace: A-Z: (UNKNOWN 0)
procedure name = test
symtree: 'a' || symbol: 'a'
type spec : (INTEGER 4)
attributes: (VARIABLE IMPLICIT-SAVE USE-ASSOC(a_mod))
symtree: 'a_mod' || symbol: 'a_mod'
type spec : (UNKNOWN 0)
attributes: (MODULE USE-ASSOC(a_mod))
symtree: 'b' || symbol: 'b'
type spec : (INTEGER 4)
attributes: (VARIABLE IMPLICIT-SAVE USE-ASSOC(b_mod))
symtree: 'b_mod' || symbol: 'b_mod'
type spec : (UNKNOWN 0)
attributes: (MODULE USE-ASSOC(b_mod))
symtree: 'c' || symbol: 'c'
type spec : (INTEGER 4)
attributes: (VARIABLE IMPLICIT-SAVE USE-ASSOC(c_mod))
symtree: 'c_mod' || symbol: 'c_mod'
type spec : (UNKNOWN 0)
attributes: (MODULE USE-ASSOC(c_mod))
symtree: 'inc_c' || symbol: 'inc_c' <---
type spec : (UNKNOWN 0) <---
attributes: (PROCEDURE MODULE-PROC USE-ASSOC(c_mod) SUBROUTINE) <---
symtree: 'test' || symbol: 'test'
type spec : (UNKNOWN 0)
attributes: (PROGRAM PUBLIC SUBROUTINE)
(例如,带箭头的行表示inc_c
可以使用例程c_mod
。)如果我们修改test.f90以附加only
关键字,
program test
use a_mod, only: inc_c
implicit none
call inc_c
end program
然后输出也相应简化:
Namespace: A-Z: (UNKNOWN 0)
procedure name = test
symtree: 'a_mod' || symbol: 'a_mod'
type spec : (UNKNOWN 0)
attributes: (MODULE USE-ASSOC(a_mod))
symtree: 'inc_c' || symbol: 'inc_c'
type spec : (UNKNOWN 0)
attributes: (PROCEDURE MODULE-PROC USE-ASSOC(c_mod) SUBROUTINE)
symtree: 'test' || symbol: 'test'
type spec : (UNKNOWN 0)
attributes: (PROGRAM PUBLIC SUBROUTINE)
所以,althogh我从来没有为此目的使用过这个选项,它可能对OP的目的有用(如果真的有必要)。