使用继承规则访问扩展主要派生类型的派生类型的组件

Accessing to components of derived types which extends main derived type by using inheritance rule

我需要一些关于使用继承规则的帮助。我的意图是使用一个派生类型数组来存储计算结果,但我也想使用该数组来存储主要和扩展派生类型的组件值。 例如,这是我要转换的示例代码:

MODULE DERIVED_TYPES

IMPLICIT NONE

! FIRST DERIVED TYPE

TYPE, PUBLIC :: DT_AA

  INTEGER, PRIVATE :: I_AA

  CONTAINS

  PROCEDURE, PUBLIC:: CALCULATE => CALC_DATA_I_AA
  PROCEDURE, PUBLIC::    T_I_AA => TAKE_DATA_I_AA

END TYPE DT_AA

PRIVATE :: CALC_DATA_I_AA
PRIVATE :: TAKE_DATA_I_AA

! SECOND DERIVED TYPE

TYPE, EXTENDS( DT_AA ), PUBLIC :: DT_BB

  INTEGER, PRIVATE :: I_BB

  CONTAINS

  PROCEDURE, PUBLIC:: CALCULATE => CALC_DATA_I_BB
  PROCEDURE, PUBLIC::    T_I_BB => TAKE_DATA_I_BB

END TYPE DT_BB

PRIVATE :: CALC_DATA_I_BB
PRIVATE :: TAKE_DATA_I_BB

CONTAINS

! TYPE DT_AA PROCEDURES

  SUBROUTINE CALC_DATA_I_AA( THIS, INDX )

    CLASS( DT_AA ) :: THIS
    INTEGER, INTENT( IN ) :: INDX

    THIS%I_AA = 1 + INDX

  END SUBROUTINE CALC_DATA_I_AA

  FUNCTION TAKE_DATA_I_AA( THIS ) RESULT( VALUE_I_AA )

    CLASS( DT_AA ) THIS
    INTEGER :: VALUE_I_AA

    VALUE_I_AA = THIS%I_AA

  END FUNCTION TAKE_DATA_I_AA

! TYPE DT_BB PROCEDURES

  SUBROUTINE CALC_DATA_I_BB( THIS, INDX )

    CLASS( DT_BB ) :: THIS
    INTEGER, INTENT( IN ) :: INDX

    THIS%I_BB = THIS%I_AA + INDX

  END SUBROUTINE CALC_DATA_I_BB

  FUNCTION TAKE_DATA_I_BB( THIS ) RESULT( VALUE_I_BB )

    CLASS( DT_BB ) THIS
    INTEGER :: VALUE_I_BB

    VALUE_I_BB = THIS%I_BB

  END FUNCTION TAKE_DATA_I_BB

END MODULE DERIVED_TYPES

PROGRAM INHERITANCE_RULE

USE, NON_INTRINSIC :: DERIVED_TYPES

IMPLICIT NONE

INTEGER :: I
INTEGER, PARAMETER :: N_CALC = 3

CLASS( DT_AA ), POINTER :: P_INH
 TYPE( DT_AA ),  TARGET :: P_A_INH( N_CALC )

DO I = 1, N_CALC

   P_INH => P_A_INH( I )

   CALL P_INH%CALCULATE( I )

   WRITE(*,*) P_INH%T_I_AA(), P_INH%T_I_BB()

END DO

END PROGRAM INHERITANCE_RULE 

在这种情况下,我不能使用指针 P_INH 和函数来获取组件 I_BB 值,这不是扩展派生类型的成员,因为我得到了这个编译错误消息:

't_i_bb' is not a member of the 'dt_aa' structure

哪种更改对这种情况有用?

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

基本上,期望的结果是调用与基类和派生类型关联的 calculate 例程,并访问与基类和派生类型关联的 take 例程。这必须通过派生类型来完成,因为基础对扩展它的类型一无所知。在不修改类型的情况下实现此目的的一种方法是:

type(dt_bb) :: b(n_calc)

do i = 1, n_calc

    call b(i)%dt_aa%calculate(i)
    call b(i)%calculate(i)

    write(*,*) b(i)%t_i_aa(), b(i)%t_i_bb()

end do

上面的输出是:

       2           3
       3           5
       4           7

应选择 calculate 调用的顺序以匹配您的用例。

编辑: 为了扩展我的评论,如果您将 calc_data_i_bb 的定义修改为:

subroutine calc_data_i_bb( this, indx )

    class( dt_bb ) :: this
    integer, intent( in ) :: indx

    call this%dt_aa%calculate(indx)
    this%i_bb = this%i_aa + indx

end subroutine calc_data_i_bb

那么你可以简化驱动循环:

type(dt_bb) :: b(n_calc)

do i = 1, n_calc

    call b(i)%calculate(i)

    write(*,*) b(i)%t_i_aa(), b(i)%t_i_bb()

end do

根据用例,这可能是更好的选择。