Module 私有,保存Fortran 90模块中变量的属性
我试图使用模块中的private属性为某些变量添加访问限制,但我需要在该模块内例程的后续调用中使用这些变量:Module 私有,保存Fortran 90模块中变量的属性,module,fortran,fortran90,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()
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的答案是肯定的,那么我认为我可以对这个变量使用save属性。如果我错了,请纠正我
这是执行此任务的正确方法吗
是的,如果在没有任何进一步规范的情况下将private语句放入模块,则将默认可访问性设置为private 对于第一个问题,Fortran 2008标准第4.5.2.2条§3规定: 如果类型定义是私有的,那么类型名以及类型的结构构造函数4.5.10只能在包含该定义的模块及其子体中访问 因此,将无法从模块或子模块子代之外的任何位置访问 对于第二个问题,可以使用save here。这与可访问性属性无关。事实上,从Fortran 2008开始,这就意味着模块变量,参见Fortran 2008标准第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内部,您创建了一个_的副本,该副本只能在模块内访问。只要calc是模块或其子模块的一部分,它就具有对a的完全访问权限。是的,如果您在没有任何进一步规范的情况下将private语句放入模块中,则将默认可访问性设置为private 对于第一个问题,Fortran 2008标准第4.5.2.2条§3规定: 如果类型定义是私有的,那么类型名以及类型的结构构造函数4.5.10只能在包含该定义的模块及其子体中访问 因此,将无法从模块或子模块子代之外的任何位置访问 对于第二个问题,可以使用save here。这与可访问性属性无关。事实上,从Fortran 2008开始,这就意味着模块变量,参见Fortran 2008标准第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内部,您创建了一个_的副本,该副本只能在模块内访问。只要calc是模块或其子模块的一部分,它就可以完全访问.以添加save属性的含义
此属性正好提供了您从F2008 5.3.16开始想要的效果:
SAVE属性指定程序单元或子程序的局部变量在执行RETURN或END语句后保留其关联状态、分配状态、定义状态和值,除非[此处不适用]
在您的示例中,A是模块的局部变量,因此是程序单元MyMod
这意味着,在调用init之后,它可能会分配一个值并设置子例程返回后保留的状态。这些值在调用calc时可用。当然,init和calc都通过主机关联引用相同的值
您提到Fortran 90,因此,正如在另一个答案中所提到的,有一个细微的变化。在Fortran 2008之前,模块变量需要在某些情况下显式地给出save属性才能产生这种效果。如果您不确定编译器是如何处理代码的,并且有些人会说这是一种很好的做法,那么显式地给出save属性没有坏处。添加save属性的含义
此属性正好提供了您从F2008 5.3.16开始想要的效果:
SAVE属性指定程序单元或子程序的局部变量在执行RETURN或END语句后保留其关联状态、分配状态、定义状态和值,除非[此处不适用]
在您的示例中,A是模块的局部变量,因此是程序单元MyMod
Th
是指,在调用init之后,它可能会分配一个值,并设置子例程返回后保留的状态值。这些值在调用calc时可用。当然,init和calc都通过主机关联引用相同的值
您提到Fortran 90,因此,正如在另一个答案中所提到的,有一个细微的变化。在Fortran 2008之前,模块变量需要在某些情况下显式地给出save属性才能产生这种效果。如果您不确定编译器是如何处理代码的,并且有些人会说这是一种很好的做法,那么显式地给出save属性并没有坏处。这是另一种在避免“save”的同时完成您想要做的事情的方法
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
这是另一种在避免“保存”的同时完成您想要做的事情的方法
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
我不确定你的第三个问题。你能详细说明一下吗?你想达到什么目的?谢谢你的回复。我知道该变量是模块专用的。我的主要问题是:我使用init初始化它,init是从使用模块的程序main.F90调用的。然后,从main.F90调用例程calc。现在,一般来说,如果变量A的作用域由于具有private属性而丢失,那么在calc中使用A是不安全的。你能详细说明一下吗?你想达到什么目的?谢谢你的回复。我知道该变量是模块专用的。我的主要问题是:我使用init初始化它,init是从使用模块的程序main.F90调用的。然后,从main.F90调用例程calc。现在,一般来说,如果变量A的范围由于具有private属性而丢失,那么在calc中使用A将不安全。谢谢您的建议。我当然会尝试使用这个想法,它似乎源于F2003的面向对象特性。你能想到这个方法和使用save属性performance-wise之间有什么区别吗?是的,F2003在派生类型中引入了过程封装。我从未测试过“save”变量的性能。但是使用save属性被认为不是一个好的编程实践。是一个比我能说得更好的评论。谢谢你的建议。我当然会尝试使用这个想法,它似乎源于F2003的面向对象特性。你能想到这个方法和使用save属性performance-wise之间有什么区别吗?是的,F2003在派生类型中引入了过程封装。我从未测试过“save”变量的性能。但是使用save属性被认为不是一个好的编程实践。这是一个比我说得更好的评论。