fortran中INTERFACE块和MODULE过程之间的区别是什么?

时间:2013-11-05 03:01:14

标签: interface module fortran procedure subroutine

我对在模块中使用接口块以及使用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语言编写,实际上这就是在我查阅的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 个答案:

答案 0 :(得分:12)

这取决于,但除非你有充分的理由相反,否则使用模块程序("在包含&#34之后;)。

那是"错误"第一种方法是必须指定过程的接口两次 - 一次在接口块中,一次在过程定义中。在第二种情况下,接口仅指定一次 - 在过程定义中。维持多个规范的需要是潜在的错误来源。

诠:

在第一个代码示例中,后一个SUBROUTINE和END SUBROUTINE语句之间的源(不在接口块内)是所谓的外部子程序。这是一个独立的程序单元。外部子程序定义了外部程序

在第二个代码示例中,在模块中的CONTAINS语句之后出现的SUBROUTINE和END SUBROUTINE语句之间的源是模块子程序。它是模块程序单元的一部分。该模块子程序定义了模块过程

(A"子程序"指的是源代码构造,而程序指的是源代码定义的东西。)

还有内部子程序(它们出现在主机外部或模块子程序或主程序中的CONTAINS语句之后),用于定义内部过程和单独的模块子程序,这是定义模块过程的另一种方式。

Fortran程序单元(主程序,模块,子模块,外部子程序,块数据)使用单独编译的模型。在编译特定的程序单元时,编译器就好像它对程序中的任何其他程序单元都没有任何意义,在源代码中明确规定了相反的内容。

这样做的一个结果是,如果您在范围中引用外部过程而没有明确地告诉编译器外部过程是什么样的,那么编译器必须从引用的方式隐式地推断出外部过程的接口( procedure有一个隐式接口)。以这种方式引用的过程不能使用该语言的许多较新的参数传递特性(因为编译器不知道如何正确地调用和传递过程的参数)。实际编译器也不太可能识别错误,例如不匹配的参数类型。

接口块(例如第一个代码示例中的接口块)可用于显式指定外部过程的接口。在源代码中可以访问显式接口的外部过程的引用可以使用所有现代参数传递功能,并且可能获得更好的编译器错误检测。但是,程序员仍然有责任确保接口主体的相关特性和实际的外部过程定义是一致的。

该语言还要求在作用域单元中只能访问过程的一个接口。在定义它的外部子程序内部,过程的接口已经是显式的,因此程序员有责任确保在外部过程中无法访问同一外部过程的接口主体。

允许在程序单元之间共享信息的显式规范之一是USE语句,该语句使得在USE语句出现的范围内可用的模块定义的事物的知识。这包括有关模块定义或声明的过程的知识。

(该语言要求在使用模块之前,模块的公共部分的源可用"这实际上意味着模块的源必须在USE语句之前编译该模块已编译完毕。)

与外部过程不同,模块过程或内部过程的接口在其标识符可访问的范围内始终是显式的 - 不需要为模块过程或内部设置接口主体(除了单独的模块子程序,一定不能有接口体。)

总结:

第一个例子 - 你有一个模块,它有一个外部过程的接口体,然后是外部过程本身。您可以引用该外部过程而无需使用该模块,在这种情况下使用隐式接口(功能有限,容易出错)。或者,如果模块在引用范围内使用,则接口将是显式的。在这种情况下,程序员必须确保接口主体和外部过程定义匹配,并且外部过程内的外部过程的接口主体不可访问。这很容易出错并且会造成维护麻烦。

第二个示例 - 您有一个具有模块过程的模块。如果没有使用相关模块,则无法通过其名称引用模块过程。这种引用的接口将始终是显式的。无需为该过程维护单独的接口主体。

第一种形式优于第二种形式的唯一理由是,如果需要打破编译依赖循环或以其他方式限制长编译依赖链。