Нужно ли ИСПОЛЬЗОВАТЬ все модули явно в основном коде DLL, или будут наследоваться переменные и методы с «самых низких» уровней, просто используя module5 и module6?
Вам не нужно для ИСПОЛЬЗОВАНИЯ модулей на всем пути к зависимостям только для доступа к сущности , если эта сущность была сделана общедоступной в используемом модуле .
Или для модуля 5 нужны два оператора USE (модуль 1 И модуль 3) ИЛИ только для модуля 3?
Просто с помощью module5
вы можете получить доступ к:
- Любая сущность модуля, объявленная внутри
module5
, помеченная как public
или protected
- Любая сущность, доступная ассоциацией USE в
module5
, помеченная public
как module5
(на самом деле общедоступность - это доступность по умолчанию, если ничего не было указано).Если к объекту обращается ассоциация USE из module1
или module3
, но помечен как private
module5
, он не будет доступен.
Я попытался охватить столькоситуации, как я мог понять в следующем примере.Я использовал только объявления переменных, но то же самое применимо к переменным, процедурам, пользовательским типам, операторам, интерфейсам ...
module module0
! Utiliy module with global constants, could be used at any level.
character(2) :: w = 'w0'
end
module module1
! Low level module. Exposes all the symbols that are not marked as private,
! both defined locally or accessed by use from 'module0'.
use :: module0
private :: z
character(2) :: x1 = 'x1', y1 = 'y1', z = 'z1'
! defined entities: w, x1, y1, z
! public entities : w, x1, y1
end
module module2
! Also low level module, but default access modifier was changed to private,
! so it exposes only symbols marked as public ('z' isn't).
use :: module0
public :: w, x2, y2
private
character(2) :: x2 = 'x2', y2 = 'y2', z = 'z2'
! defined entities: w, x2, y2, z
! public entities : w, x2, y2
end
module module3
! Uses all public names from 'module1' (including 'w' that is from 'module0'),
! but only exposes some of them. Also, defines and exposes local symbols.
use :: module1
private :: x3, y1
character(2) :: x3 = 'x3', y3 = 'y3'
! defined entities: w, x1, y1, x3, y3
! public entities : w, x1, y3
end
module module4
! Here, only selected symbols are accessed from 'module2', and 'w' has been
! renamed into 'w2' to avoid name-conflict with locally defined name 'w'
! (a compile error would had been thrown).
use :: module2, only: w2 => w, x2
public :: w, x2, y4
private
character(2) :: w = 'w4', x4 = 'x4', y4 = 'y4'
! defined entities: w, w2, x2, x4, y4
! public entities : w, x2, y4
end
module module5
! This module can use symbols from lowest level modules that are made public
! by 'module3', without explicitly using those modules.
use :: module3
character(2) :: z = 'z5'
! defined entities: w, x1, y3, z
! public entities : w, x1, y3, z
end
module module6
! As 'y2' is not exposed by 'module4', we could have access to it by using
! 'module2' directly. There is no name-conflict between 'w' from 'module0'
! and from 'module2' because both relate to the same entity. There would be
! conflict with 'w' from 'module4' though, hence the rename.
use :: module0
use :: module2
use :: module4, w4 => w
public :: w, x2, y4, z
private
character(2) :: z = 'z6'
! defined entities: w, w4, x2, y2, y4, z
! public entities : w, x2, y4, z
end
Я настоятельно советую вам использовать явный импорт всякий раз, когда это возможно, так как это делаетВаш код более понятен и избегает конфликтов имен.Как правило, попробуйте использовать разные имена для открытых сущностей в модулях или используйте предложения переименования в операторах USE.
Это пример использования предыдущих модулей:
program main
! There aren't namespaces in Fortran (yet), so attention shall be paid when
! naming symbols meant to be accessed by use association, to avoid conflicts.
! That's why explicit imports are encouraged, as well as implicit none.
use :: module5
use :: module6, z6 => z
implicit none
character(2) :: v = 'v#'
call test_a
call test_b
call test_c
contains
subroutine test_a
! You can access used and defined names in procedures by host association.
print '(5a3)', v, w, x1, y3, z ! output: v# w0 x1 y3 z5
print '(5a3)', v, w, x2, y4, z6 ! output: v# w0 x2 y4 z6
end
subroutine test_b
! Also, you can use modules locally inside procedures. In this case, local
! names "shadow" host associated names, as with 'z' from 'module6' here.
use :: module6
print '(5a3)', v, w, x2, y4, z ! output: v# w0 x2 y4 z6
end
subroutine test_c
! There is no name-conflict error between host and local symbols; the local
! definition (or use association) always "shadows" the host associated name.
use :: module4, only: w
character(2) :: v = 'v_', z = 'z_'
print '(5a3)', v, w, x1, y3, z ! output: v_ w4 x1 y3 z_
end
end
Для полноты картины я бы упомянул, что стандарт Fortran 2018 включает новую функцию с именем Доступность по умолчанию для сущностей, доступ к которым осуществляется из модуля , который позволяет установить модульимя в операторе public
или private
, применяющем указанный модификатор доступности ко всем используемым объектам из этого модуля.
Если модуль a использует модуль b, доступность по умолчанию для объектов, к которым он обращается из bявляется публичным.Указание другой доступности для каждого объекта неудобно и подвержено ошибкам.Теперь возможно, чтобы имя модуля было включено в список имен объектов, которые становятся публичными или частными в публичном или частном заявлении.Это устанавливает значение по умолчанию для всех сущностей, доступных из этого модуля.
Единственный известный мне сегодня компилятор (2018), который включает эту функцию, - Intel Visual Fortran 19.0 .