首页 > 解决方案 > 将模块变量设为私有

问题描述

在过去的几年里,我一直在创建几个带有子例程的模块,然后将它们用于不同的项目。当我在与这些模块中定义的变量名称冲突的项目特定文件之一中定义参数变量时,我遇到了问题。是否可以将这些名称设为子程序私有或模块私有?

这是一个例子。假设我有以下模块:

module mymod

   implicit none
   contains

   subroutine test1(x)
      real, intent(in) :: x(:)
      print *, x**2.0  

   end subroutine test1

end module mymod

然后这个模块被主程序调用

program main

   use mymod
   implicit none

   real :: y
   real,dimension(2,1),parameter :: x = [1.0,2.0]

   y = 3.0
   call test1(y)

end program main

在这种情况下,由于x在主程序中定义为与x子程序不同维度的参数,test1编译时会出现问题(违反形状匹配规则)。有没有办法x在模块内使模块mymod私有?

我知道一个选项可能是在我的模块中使用“非常见”变量名称或有一个禁止名称列表,但这在这一点上似乎很复杂(需要编辑太多文件并且失去与这些书籍/论文的符号一致性概述了程序),并且会使与同事的协作更加困难。

标签: modulefortran

解决方案


两个不同的问题合二为一:

为什么示例程序无法编译:

这与公共或私有无关,或x在程序本身中定义。

x这与在模块中作为参数定义为一维数组而在主程序中y是标量这一事实有关。

试试看,去掉x主程序中的声明,还是会失败。

(事实上​​,声明无论如何都不会那样工作,您声明x为二维数组(形状 2, 1),然后给它一个一维数组。您必须执行以下操作:

real, dimension(2, 1), parameter x = reshape([1.0, 2.0], [2, 1])

但是要摆脱您描述的错误,您要么需要通过删除(:)后面的来更改子例程接口real, intent(in) :: x,要么将调用更改为call test1([y]).

当 2 个模块导入不同的同名变量时,你可以做什么:

如果你说有这个会有所不同:

module modA
    implicit none
    real, parameter :: x = 2.0
contains
    subroutine subA(k)
        real, intent(in) :: k
        print *, k*x
    end subroutine subA
end module modA

module modB
    implicit none
    real :: x(3)
end module modB

program progtest
    use modA
    use modB
    implicit none
    call subA(x(1))
end program progtest

在此示例中,它将尝试x从两个模块中导入变量。

避免它的方法:

  1. 将其设为x私有:

    implicit none
    real, parameter, private :: x = 2.0
    

    或者

    real, parameter :: x = 2.0
    private :: x
    

    或者

    implicit none
    private
    real, parameter :: x = 2.0
    public :: subA
    
  2. 只导入您需要的部分:

    program progtest
        use modA, only: subA
        use modB
        implicit none
    ...
    
  3. 重命名其中一个或两个x

    use modA
    use modB, only: xB => x
    ...
    call subA(xB(1))
    

推荐阅读