Сделать переменные модуля приватными - PullRequest
1 голос
/ 26 марта 2019

За последние несколько лет я создал несколько модулей с подпрограммами, которые затем использую для различных проектов.У меня возникают проблемы, когда я определяю переменные параметров в одном из тех файлов проекта, которые конфликтуют с именем переменной, определенной в этих модулях.Можно ли сделать эти имена частными или подпрограммными?

Вот пример.Предположим, у меня есть следующий модуль:

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 частным в модуле?

Я знаю, что вариант может заключаться в том, чтобы использовать «не общие» имена переменных в моих модулях или иметь список запрещенных имен, но это кажется сложным на данный момент (требует редактирования слишком большого количества файлов и потери согласованности обозначений с книгами / бумагами, в которых изложены эти процедуры), и затруднит сотрудничество с коллегами.

1 Ответ

0 голосов
/ 26 марта 2019

Два разных вопроса в одном:

Почему пример программы не удается скомпилировать:

Это не имеет ничего общего с публичным или приватным, или x, определяемым в самой программе.

Все это связано с тем, что в модуле x в качестве параметра определяется как массив 1-й, а в основной программе y - скаляр.

Попробуйте, удалите объявление x в основной программе, и оно все равно не будет работать.

(На самом деле, объявление в любом случае не работает так, вы объявляете x как двумерный массив (форма 2, 1), но затем присваиваете ему 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))
    
...