Доступ к компонентам производных типов, который расширяет основной производный тип, используя правило наследования - PullRequest
0 голосов
/ 26 июня 2018

Мне нужна небольшая помощь по использованию правил наследования.Мое намерение состоит в том, чтобы использовать один массив производного типа для хранения результатов вычислений, но я хочу использовать этот массив также для хранения значений компонентов из основного и расширенного производных типов.Например, это мой пример кода, который я хочу преобразовать:

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.

1 Ответ

0 голосов
/ 26 июня 2018

По сути, желаемым результатом является вызов подпрограмм 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 должен быть выбран в соответствии с вашим вариантом использования.

Edit: Чтобы расширить мой комментарий, если вы измените определение 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

Это может быть лучшим вариантом в зависимости от варианта использования.

...