关于使用继承规则,我需要一些帮助。我的意图是使用一个派生类型数组存储计算结果,但我也想使用该数组存储主派生类型和扩展派生类型的组件值。 例如,这是我要转换的示例代码:
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。
答案 0 :(得分:2)
从根本上讲,所需的结果是调用与基本和派生类型关联的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
根据使用情况,这可能是一个更好的选择。