【问题标题】:Puting derived types with procedures from module to submodule将派生类型与过程从模块放到子模块
【发布时间】:2018-06-22 14:24:35
【问题描述】:

我需要一些关于使用子模块的帮助。我的意图是为父模块的特定派生类型使用一个子模块,并且我想将派生类型的整个声明放入子模块中。例如,这是我要转换的示例代码:

MODULE PARENT_MODULE

IMPLICIT NONE

TYPE , PUBLIC :: DERIVED_TYPE_A

  PRIVATE

  INTEGER :: I_00

  CONTAINS

  PROCEDURE , PUBLIC :: CALC_I_00 => CALC_DATA_I_00
  PROCEDURE , PUBLIC :: TAKE_I_00 => TAKE_DATA_I_00

END TYPE DERIVED_TYPE_A

PRIVATE :: CALC_DATA_I_00
PRIVATE :: TAKE_DATA_I_00

INTERFACE

  MODULE SUBROUTINE CALC_DATA_I_00( THIS , NUM_00 )

    CLASS( DERIVED_TYPE_A ) :: THIS
    INTEGER , INTENT( IN ) :: NUM_00

  END SUBROUTINE CALC_DATA_I_00

  MODULE FUNCTION TAKE_DATA_I_00( THIS ) RESULT( RES )

    CLASS( DERIVED_TYPE_A ) :: THIS
    INTEGER :: RES

  END FUNCTION TAKE_DATA_I_00

END INTERFACE

END MODULE PARENT_MODULE

SUBMODULE( PARENT_MODULE ) TYPE_A

CONTAINS

MODULE PROCEDURE CALC_DATA_I_00

  THIS%I_00 = NUM_00 + 2

END PROCEDURE CALC_DATA_I_00

MODULE PROCEDURE TAKE_DATA_I_00

  RES = THIS%I_00

END PROCEDURE TAKE_DATA_I_00

END SUBMODULE TYPE_A

PROGRAM TYPE_SUBMODULES

USE , NON_INTRINSIC :: PARENT_MODULE

IMPLICIT NONE

INTEGER :: I

CLASS( DERIVED_TYPE_A) , POINTER :: P_ARR_INT
TYPE( DERIVED_TYPE_A ) , DIMENSION( 3 ) , TARGET :: ARR_INT

D00: DO I = 1 , 3

        P_ARR_INT => ARR_INT( I )

        CALL P_ARR_INT%CALC_I_00( I )

        WRITE( * , * ) ARR_INT( I )%TAKE_I_00()

     END DO D00

END PROGRAM TYPE_SUBMODULES

有没有办法在子模块中使用派生类型(带有组件和过程)?比如这样:

SUBMODULE( PARENT_MODULE ) TYPE_A

  TYPE :: D_TYPE_A

    INTEGER :: I_00

    CONTAINS

  !  PROCEDURE :: CALC_I_00 => CALC_DATA_I_00
  !  PROCEDURE :: TAKE_I_00 => TAKE_DATA_I_00

  END TYPE D_TYPE_A

  CLASS( D_TYPE_A ) , POINTER :: P_ARR_INT
  TYPE( DERIVED_TYPE_A ) , DIMENSION( 3 ) , TARGET :: ARR_INT

CONTAINS

!MODULE SUBROUTINE CALC_DATA_I_00( THIS )
!
!    CLASS( D_TYPE_A ) :: THIS
!   ! INTEGER , INTENT( IN ) :: NUM_00
!
!    THIS%I_00 = NUM_00 + 1
!
!END SUBROUTINE CALC_DATA_I_00
!
!!FUNCTION TAKE_DATA_I_00( THIS ) RESULT( RES_00 )
!!
!!    CLASS( D_TYPE_A ) :: THIS
!!    INTEGER :: RES_00
!!
!!    RES_00 = THIS%I_00
!!
!!END FUNCTION TAKE_DATA_I_00

END SUBMODULE TYPE_A

在这种情况下,我不能在主程序中使用指针和目标变量,我想这样做,或者是否可以在 PARENT_MODULE 中声明指针和目标变量。

我的 IDE 是带有 Gfortran 编译器的 Code::Blocks 17.12。编译器版本为:MinGW 6.3.0。

【问题讨论】:

  • 算一下你有多少问题:1)如何(以及为什么)使用子模块,2)如何避免为每种类型创建一个文件(与子模块无关)? 3)是否可以在子模块中使用私有和公共? 4)是否可以在没有显式接口的情况下使用过程? 5)如何在父模块中使用接口块? 6)如何使类型为私有的元素? 7)如何公开类型程序?您需要关注您希望您的问题得到任何关注。
  • 我同意这一点。我们实际上有一个过于宽泛的理由来结束问题。请在每个帖子中提出一个问题。
  • @VladimirF 我需要提出新问题还是重新提出现有问题?
  • 你可以重新制定这个。
  • @VladimirF 如果我有 34 个派生类型并且我需要在派生类型编号 32 的过程中使用派生类型编号 16 或者如果我需要使用相同意义上的指针等等。 .如果我将每个派生类型放在项目中的单独文件中,在某个阶段,我会遇到循环依赖问题。

标签: fortran


【解决方案1】:

有没有办法在子模块中使用派生类型(带有组件和过程)?

简短回答:。 (至少不是你期望的那样)

子模块是添加到语言中的一项功能,用于解决一个特定问题:接口和实现的分离。主要动机是当您只需要更改模块中的实现细节时生成的编译级联。

但是子模块不是模块!

子模块与模块相关联,并为在该模块中声明的过程提供实现。因此,子模块可以访问其父模块中的所有声明。尽管如此,该模块对它的子模块一无所知,并且不会像模块一样使用它的子模块。该模块只是希望您在链接时添加子模块,足以覆盖所有缺少的过程实现。

因此,如果您要在子模块中声明一个类型或其他任何内容,那么它将是本地的并且对父模块是不透明的。

如果您需要在另一个单元中通过主机访问程序统一性的声明,那么您需要一个模块。

您必须明智地设计解决方案。按主题和依赖项分隔您的模块。如果三个类型相互引用,那么它们非常相关应该在同一个程序单元中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-11-18
    • 2019-03-21
    • 1970-01-01
    • 2020-12-27
    • 1970-01-01
    • 1970-01-01
    • 2016-08-23
    相关资源
    最近更新 更多