Какова разница между интерфейсным блоком и процедурой модуля в fortran?

Я немного смущен использованием блока интерфейса внутри модуля и использованием инструкции CONTAINS для создания "явного интерфейса" для процедуры внутри модуля.

обычно я пишу процедуру, используя блок интерфейса внутри модуля. Например,

    MODULE ModExample
    INTERFACE 
        SUBROUTINE Sumatory(a, b, c)
            IMPLICIT NONE

            INTEGER, INTENT(IN)::a
            INTEGER, INTENT(OUT)::b
            INTEGER, INTENT(OUT)::c
        END SUBROUTINE Sumatory
    END INTERFACE
    END MODULE ModExample

   SUBROUTINE Sumatory(a, b, c)
      IMPLICIT NONE

      INTEGER, INTENT(IN)::a
      INTEGER, INTENT(OUT)::b
      INTEGER, INTENT(OUT)::c

      !Executable statements here

   END SUBROUTINE Sumatory

и это работает для меня. Но он также может быть написан с помощью CONTAINS stament внутри модуля, и на самом деле это способ, которым процедуры примера написаны в Fortran книги, с которыми я консультировался.

MODULE ModExample

CONTAINS

SUBROUTINE Sumatory(a, b, c)
    IMPLICIT NONE

    INTEGER, INTENT(IN)::a
    INTEGER, INTENT(OUT)::b
    INTEGER, INTENT(OUT)::c

    !Executable statements here

END SUBROUTINE Sumatory
END MODOULE ModExample

Итак, что случилось с блоком INTERFCE? Оба эквивалентных конструкций? Какой из двух передников мне использовать? Возможно, на все эти вопросы можно ответить большим "это зависит", но я хотел бы, чтобы вы объяснили свои различия. Спасибо заранее.

1 ответов


Это зависит, но если у вас нет веской причины наоборот, используйте процедуры модуля ("после contains").

то, что" неправильно " с первым подходом, заключается в том, что вам пришлось указать интерфейс процедуры дважды - один раз в блоке интерфейса и один раз в самом определении процедуры. Во втором случае интерфейс указывается только один раз - в определении процедуры. Потребность поддерживать множественные спецификации потенциальный источник ошибка.

разработка:

в первом примере кода источником между последней подпрограммой и операторами конечной подпрограммы (не внутри блока интерфейса) является то, что известно как внешние подпрограммы. Это программная единица сама по себе. Внешняя подпрограмма определяет внешняя процедура.

во втором примере кода источник между инструкциями подпрограммы и конечной подпрограммы, который появляется после Содержит оператор в модуле, является модуль подпрограммы. Он является частью модуля программного блока. Эта подпрограмма модуля определяет процедура модуля.

("подпрограмма" относится к конструкции исходного кода, в то время как процедура относится к тому, что определяет исходный код.)

существуют также внутренние подпрограммы (они появляются после оператора CONTAINS внутри подпрограммы внешнего хоста или модуля или основной программы), которые определяют внутренние процедуры и отдельные подпрограммы модуля, которые являются еще одним способом определения процедур модуля.

программные блоки Fortran (основные программы, модули, подмодули, внешние подпрограммы, данные блока) используют модель раздельной компиляции. При компиляции конкретного программного блока компилятор действует так, как если бы он не обращал внимания на любой другой программный блок в программе, исключая явные спецификации в источнике наоборот.

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

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

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

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

(язык требует, чтобы источник для публичной части модуля "быть доступно " перед использованием модуля, что практически означает, что источник для модуля должен быть скомпилирован до компиляции инструкции USE для модуля.)

В отличие от внешних процедур, интерфейс для процедуры модуля или внутренней процедуры всегда является явным в области, где доступен его идентификатор - нет необходимости иметь тело интерфейса для процедуры модуля или внутренней (отдельные подпрограммы модуля в стороне, вы не должны иметь интерфейс тело.)

в итоге:

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

второй пример - у вас есть модуль, который имеет процедура модуля. Вы не можете ссылаться на процедуру модуля через его имя без использования соответствующего модуля. Интерфейс для такой ссылки всегда будет явным. Никакая потребность поддерживать отдельное тело интерфейса для процедура.

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