【问题标题】:Accessing to components of derived types which extends main derived type by using inheritance rule使用继承规则访问扩展主要派生类型的派生类型的组件
【发布时间】:2018-06-27 03:12:23
【问题描述】:

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

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 是带有 Gfortran 编译器的 Code::Blocks 17.12。编译器版本为:MinGW 6.3.0。

【问题讨论】:

  • @HighPerformanceMark 我想同时对两个结构进行计算,我想通过函数取值。有没有办法做到这一点?
  • 有什么用?修复错误信息?还是为了实现别的目标?
  • @VladimirF 我可以通过声明不同的数组来修复错误,但在这种情况下,我将无法获得I_AA 的正确结果。
  • 您希望/希望 I_AAI_BB 的值在您的循环之后?
  • @ptb 我想得到这个结果[2,3], [3,4], [5,6],我想把这些结果存储在数组P_A_INH

标签: fortran gfortran


【解决方案1】:

从根本上说,期望的结果是调用与基类型和派生类型关联的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

这可能是更好的选择,具体取决于用例。

【讨论】:

  • 从最终结果的角度来看,这个解决方案是正确的,但是......我想知道是否有可能通过一次调用函数 calculation 来获得正确的结果,或者它是不可能的全部。
  • 这两个函数调用必须显式进行。您可以将调用this%dt_aa%calculate 移动到calc_data_i_bb 以尝试隐藏它,但它仍然是两个函数调用
  • 这很好,因为我想隐藏到从主机程序调用的模块。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-07-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多