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
Следуя предложениям, предложенным Россом и Владимиром Ф.,
одна возможность может быть:
(i’) иметь однозначное соответствие между модулями и подпрограммами,
(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: Спасибо, что указали на предыдущий пост, в котором ассоциация наследуется. Однако у меня сложилось впечатление, что это решает только половину моей проблемы; конструкция, обсуждаемая в этом посте, иллюстрирует, как можно запретить вызывающей программной единице доступ к объектам вызываемой программной единицы, которые должны оставаться скрытыми (опции «использовать только» и/или «частные»), но я не могу с уверенностью утверждать, что сущности вызывающей программной единицы, не связанные с аргументами, останутся недоступными для вызываемой программной единицы.
private
? - person Ross   schedule 02.10.2017