Моя точка зрения состояла в основном в том, чтобы избежать доступа к переменным модуля, которые определены в том же модуле и которые должны использоваться другими процедурами модуля, и как избежать доступа к ним.

1

вопрос связан с вызовом и вызываемыми подпрограммами в Fortran 90. Я совершенно запутался в правилах ассоциации host / use / arguments; У меня проблемы с пониманием логики определения объема, вытекающей из этих правил. Возможно, самый простой способ разоблачить мою проблему - объяснить, чего я хотел бы достичь и почему.

Я хотел бы удовлетворить два требования дизайна:

(i) Вызывающая подпрограмма только позволяет вызываемой подпрограмме получить доступ к своим объектам, которые передаются в качестве аргументов, никаким другим. (ii) Вызываемая подпрограмма не позволяет вызывающей подпрограмме получить доступ к любому из объектов, которые она определяет локально.

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

2

Конечно, Fortran 90 предлагает возможность использовать модули и вариант «только». Например, можно сделать следующее:

module my_mod_a
contains
subroutine my_sub_a
    use my_mod_b, only: my_sub_b
    …
    call my_sub_b(arg_list_b)
    …
end subroutine my_sub_a
end module my_mod_a
!………
module my_mod_b
contains
subroutine my_sub_b(arg_list_b’)
    do stuff with arg_list_b’
end my_sub_b
…
end module my_mod_b
!………

Конечно, my_sub_a будет максимально разрешен доступ к тем объектам my_mod_b, для которых my_sub_b является областью видимости. Но сможет ли он получить доступ к объектам my_sub_b, отличным от списка аргументов, который он передает? В частности, сможет ли my_sub_a получить доступ к объектам, локальным для my_sub_b? И наоборот, разрешает ли ассоциация использования my_sub_b обращаться к объектам my_sub_a, отличным от тех, которые передаются в качестве фактических аргументов?

3

Является ли следующая конструкция «буферного модуля» достаточной для того, чтобы соответствовать требованиям # 1?

module my_mod_a
contains
subroutine my_sub_a
    use my_mod_b_shell, only: my_sub_b_shell
    …
    call my_sub_b_shell(arg_list_b)
    …
end subroutine my_sub_a
end module my_mod_a
!………
module my_mod_b_shell 
contains
subroutine my_sub_b_shell(arg_list_b’)
!passes arguments, does not do anything else
    use my_mod_b, only: my_sub_b
    call my_sub_b(arg_list_b’)
end my_sub_b_shell
end module my_mod_b_shell
!………
module my_mod_b
contains
subroutine my_sub_b(arg_list_b’)
    do stuff with arg_list_b’
end my_sub_b
…
end module my_mod_b
!………
4

Есть ли более простая конструкция для достижения целей # 1?

5

Следуя предложениям, предложенным Россом и Владимиром Ф.,

одна возможность может быть:

(я), чтобы иметь взаимно-однозначное соответствие между модулями и подпрограммами,

(ii) объявлять локальные переменные в модуле вместо подпрограммы; затем можно пометить локальные переменные как «частные».

Просто чтобы быть уверенным, что я правильно понял, вот тривиальная программа, которая иллюстрирует (i ') и (ii'):

program main

use sub_a_module
implicit none

double precision :: x

x=0.0d+0
write(*,*) 'x ante:',x
call sub_a(x)
write(*,*) 'x post:',x

end program main
!-------------------------------------------------
module sub_a_module

double precision, private :: u0
double precision, private :: v0
contains
!.-.-.-.-.-.-.-.-
subroutine sub_a(x)

   use sub_b_module
   implicit none

   double precision :: x

   u0=1.0d+0
   v0=2.0d+0
   call sub_b(v0)
   x=x+u0+v0

end subroutine sub_a
!.-.-.-.-.-.-.-.-
end module sub_a_module
!-------------------------------------------------
module sub_b_module

double precision, private :: w0
contains
!.-.-.-.-.-.-.-.-
subroutine sub_b(v)

   implicit none
   double precision :: v

   w0=1.0d-1
   v=v+w0

end subroutine sub_b
!.-.-.-.-.-.-.-.-
end module sub_b_module

В этом примере единственная сущность sub_a, к которой может обращаться sub_b, - это v0 (связь аргументов); u0 останется скрытым для sub_b. И наоборот, тег 'private' гарантирует, что переменная w0 остается вне области действия sub_a, даже если sub_a ИСПОЛЬЗУЕТ модуль sub_b_module. Это правильно?

@Ross: Спасибо, что указали на предыдущий пост, где связь унаследована. Однако у меня сложилось впечатление, что это касается только половины моей проблемы; конструкция, обсуждаемая в этом посте, иллюстрирует, как можно запретить программному модулю вызывающей стороны получить доступ к объектам вызываемого программного модуля, которые должны оставаться скрытыми (опции «использовать только» и / или «частные»), но я не могу с уверенностью утверждать, что объекты программной единицы вызывающей стороны, которые не связаны с аргументами, останутся недоступными для вызываемой программной единицы.

Ответы на вопрос(2)

Ваш ответ на вопрос