私有,保存Fortran 90模块中变量的属性

时间:2015-12-15 19:04:58

标签: module fortran fortran90

我正在尝试在模块中为某些变量(使用private属性)添加访问限制,但我需要在该模块中的例程的后续调用中使用这些变量:

module MyMod

  private 
  integer,allocatable :: A(:)

  public :: init,calc

contains

  subroutine init()

    ! allocating and initializing A

  end subroutine init

  subroutine calc()

    ! Using A

  end subroutine

 end module

问题:

  1. 这是真的,私有变量不在use这个模块的程序范围内。

  2. 如果1的答案是肯定的,那么我认为我可以对此变量使用save属性。如果我错了,请纠正我?

  3. 这是执行此任务的正确方法吗?

3 个答案:

答案 0 :(得分:3)

是的,如果您在没有任何进一步说明的情况下将私有语句放入模块中,则将默认辅助功能设置为private

对于第一个问题,Fortran 2008标准(Cl.4.5.2.2§3)指出:

  

如果类型定义是private,那么类型名称以及类型的结构构造函数(4.5.10)只能在包含定义的模块中及其后代中访问。

因此,无法从模块或子模块(后代)之外的任何位置访问A

对于第二个问题,是 - 你可以在这里使用save。 (这与辅助功能属性无关)。实际上,从Fortran 2008开始,模块变量就是隐含的,参见Fortran 2008 Standard(Cl.5.3.16§4)[感谢@francescalus]:

  

在主程序,模块或子模块的作用域单元中声明的变量,公共块或过程指针隐式具有SAVE属性,可以通过显式规范确认[...]

如果我理解你的第三个问题,那就与初始化有关。您可以使用函数/子例程来实现这一点,您可以将数组传递给它进行初始化:

module MyMod
! ...
contains
! ...
subroutine init( A_in )
  implicit none
  integer, intent(in) :: A_in(:)

  ! allocating and initializing A
  allocate( A(size(A_in)) )
  A = A_in
end subroutine

end module

init()内,您可以创建A_in的副本,该副本只能在模块中访问。只要calc()是模块(或其子模块)的一部分,它就可以完全访问A

答案 1 :(得分:1)

添加answer by Alexander Vogt save属性的含义。

此属性精确地给出了您之后的效果(来自F2008 5.3.16):

  

SAVE属性指定程序单元或子程序的局部变量在执行RETURN或END语句后保留其关联状态,分配状态,定义状态和值,除非[此处不适用]

在您的示例中,A是模块的局部变量(因此是程序单元)MyMod

这意味着,在调用init之后,可能会分配A并设置在子例程返回后保留状态的值。然后,可以通过调用calc获得这些值。当然,initcalc都指向相同的A到主机关联。

你提到Fortran 90,所以有一个微妙的变化(再次提到其他答案)。在Fortran 2008模块变量之前,需要save属性在某些情况下明确地给出此效果。如果您不确定编译器如何处理代码,那么明确提供save属性是没有害处的(无论如何,有些人会说它是一种好的做法)。

答案 2 :(得分:1)

这是在避免“保存”的同时完成您想要做的事情的另一种方式。

module MyMod

  private
  public :: myType, init

  type myType
    private
    integer, allocatable :: A(:)
  end type myType

contains

  subroutine init(obj, n)

    type(myType), intent(inout) :: obj
    integer, intent(in) :: n

    allocate(obj%A(n), source=-9999999)

  end subroutine init

end module MyMod

program test

  use MyMod, only: myType, init 

  type(myType) :: m ! m is an opaque object

  call init(m, 10)

end program test

在这个例子中,m是一个不透明的对象 - 我可以创建对象,传递它,但不能访问它的内容(在这种情况下是数组A)。这样,我隐藏了我的数据。只要我的对象m在范围内,我就可以通过模块myMod中包含的例程对隐藏在对象中的数据进行操作。

如果您可以访问支持Fortran 2003的现代编译器,则可以将模块重写为

module MyMod

  private
  public :: myType

  type myType
    private
    integer, allocatable :: A(:)
  contains
    procedure, public :: init
  end type myType

contains

  subroutine init(obj, n)

    class(myType), intent(inout) :: obj
    integer, intent(in) :: n

    allocate(obj%A(n), source=-9999999)

  end subroutine init

end module MyMod

program test

  use MyMod, only: myType

  type(myType) :: m ! m is an opaque object                                                         

  call m%init(10)

end program test