2

I'm trying to build an allocatable array with polymorphic elements. A minimal example is the following :

program PolyArray

implicit none

type basetype
    integer :: ib
end type basetype

type, extends(basetype) :: exttype1
    real    :: r1
end type exttype1

type, extends(exttype1) :: exttype2
    real    :: r2
end type exttype2

type arraytype
    class(basetype), allocatable :: comp
end type arraytype

type(arraytype), dimension(:), allocatable :: ary
integer :: N, i 

N = 5
allocate (ary(N))
do i=1,N; if (mod(i,2)==0) then
    allocate(exttype2::ary(i)%comp)
     else if (       i==1) then
    allocate(basetype::ary(i)%comp)
        else
    allocate(exttype1::ary(i)%comp)
end if; end do

do i=1,N; select type (this=>ary(i)%comp)
    type is (basetype)
        write(*,*) i, "is basetype"!, "%ib =", ary(i)%comp%ib
    type is (exttype1)
        write(*,*) i, "is exttype1"!, "%r1 =", ary(i)%comp%r1
    type is (exttype2)
        write(*,*) i, "is exttype2"!, "%r2 =", ary(i)%comp%r2
    class default
        write(*,*) i, "is unknown type !"
end select; end do

end program PolyArray

Now, the code above works fine and prints out (as expected) :

           1 is basetype
           2 is exttype2
           3 is exttype1
           4 is exttype2
           5 is exttype1

The problem is, however, once I try to access the component of each extended type (e.g. r1 of exttype1) by uncommenting the commented part of each write(*,*) line, my compiler (gfortran 7.5.0) gives the following error :

         write(*,*) i, "is exttype1", "%r1 =", ary(i)%comp%r1
                                                            1
Error: 'r1' at (1) is not a member of the 'basetype' structure
poly.f90:40:60:

         write(*,*) i, "is exttype2", "%r2 =", ary(i)%comp%r2
                                                            1
Error: 'r2' at (1) is not a member of the 'basetype' structure

I don't understand why these errors are produced since the compiler obviously recognizes the extended types exttype1 and exttype2. What's the correct way to access r1 and r2?

EDIT : By changing ary(i)%comp to this in each write(*,*) line, the code compiles normally. What difference does this modification make? How are these two NOT equivalent?

4

1 回答 1

1

在选择类型构造中

select type (this=>ary(i)%comp)

有两件事:选择器关联名称ary(i)%comp是这里的选择器并且this是关联名称。

我们知道在这种情况下需要关联名称,因为ary(i)%comp它不是名称。

但是,关联名称不仅仅是为了方便(就像它可能在关联构造中):它具有您在此处需要的基本必需属性。在类型保护管理的块中,关联名称给出的变量已声明类型保护的类型;选择器保留声明的类型,就像它在构造之外一样。

拥有所需的声明类型允许我们访问组件;仅仅拥有动态类型不会。

于 2020-03-25T16:28:48.293 回答