我试图创建一组与一个对象共享继承的派生类型的全局可用可分配数组。 Fortran似乎并没有让这很容易。以下是我到目前为止的情况。
首先是带有可分配数组的派生类型和模块。
Module Environment
use Entity_M
type(Entity_C), dimenion(:), allocatable :: objects
End Module Environment
Module Entity_M
type Entity_T
integer :: id
real*8 :: time
real*8, dimension(3) :: currPos
type(TrajectoryDatum), dimension(:), allocatable :: trajTable
end type Entity_T
type Entity_C
class(Entity_T), pointer :: e
end type Entity_C
type, extends(Entity_T) :: Aircraft_T
real*8 :: altitude
end type Aircraft_T
type, extends(Entity_T) :: Missile_T
integer :: targetID
end type Missile_T
End Module Entity
现在是主程序
Program Main
use Initialization
use Environment
use Entity_M
call simInit(3)
write(*,*) objects%trajTable !<---- this does not persist
call runSim()
End Program Main
带问题的代码
Module Initialization
use Entity_M
contains
subroutine simInit(numOfObjects)
integer, intent(in) :: numOfObjects
call objectsInit(numOfObjects)
call launchersInit()
end subroutine simInit
subroutine objectsInit(numOfObjects)
use Environment
integer, intent(in) :: numOfObjects
!local
type(Aircraft_T) :: aircraft
integer :: i
allocate(objects(numOfObjects)
do i = 1, numOfObjects
aircraft%trajTable = getTrajectoryData()
call allocatePointer(objects(i)%e, aircraft)
end do
end subroutine objectsInit
subroutine allocatePointer(c, t)
class(Entity), pointer, intent(out) :: c
type(Aircraft), target, intent(in) :: t
c => t
end subroutine allocatePointer
End Module Initialization
以上只是在没有编译器的计算机上编写的示例代码。我尽力而为,如果有拼写错误,他们很少。我尽力反映原始代码的结构。
问题是字段&#34;对象%trajTable&#34;在离开&#34; objectsInit&#34;之后返回到未定义的指针。子程序。其他值如time,id和currPos仍然是正确的。我怎么能纠正这个?
我正在使用Visual Studio 2012和Intel Visual Fortran 2015。
答案 0 :(得分:2)
由于该程序有许多重叠的名称(如飞机和飞机,在Fortran中被认为是相同的),我附上了&#34; _t&#34;所有类型(例如,飞机到飞机等)和&#34; _m&#34;所有模块名称(例如,Entity to Entity_m)使程序工作(至少正式)。
更重要的是,正如@innoSPC上面评论的那样,type(Aircraft) :: aircraft
是一个局部变量,所以我认为退出objectsInit()
后与之关联的指针变得不确定。该代码适用于
call allocatePointer( objects( i )% e, aircraft )
替换为
allocate( objects( i )% e, source=aircraft )
以便为每个objects( i )% e
提供一个独立的记忆,其中包含Aircraft_t的类型,并将飞机内容复制到其中。
编辑以下是我用于测试的最小示例。
Module Entity_m
implicit none
type Entity_t !! base type
integer :: trajTable( 2 )
endtype
type, extends(Entity_t) :: Aircraft_t
real*8 :: altitude
endtype
type, extends(Entity_t) :: Missile_t !! dangerous...
integer :: targetID
endtype
type Entity_c !! container type
class(Entity_t), pointer :: e
endtype
type(Entity_c), allocatable :: objects(:)
contains
subroutine objectsInit( numObj )
integer :: numObj
!local
type(Aircraft_t) :: aircraft
type(Missile_t) :: missile
integer :: i
allocate( objects( numObj ) )
do i = 1, numObj
if ( mod( i, 2 ) == 1 ) then
aircraft% trajTable(:) = i
aircraft% altitude = 10.0d0 * i
allocate( objects( i )% e, source= aircraft )
else
missile% trajTable(:) = 10000 * i
missile% targetID = -100 * i
allocate( objects( i )% e, source= missile ) !! missile loaded !!
endif
enddo
endsubroutine
EndModule
Program Main
use Entity_m
call objectsInit( 3 )
do i = 1, 3
print *, objects( i )% e% trajTable(:) !! access members of base type
select type ( t => objects( i )% e ) !! access members of derived type
type is ( Aircraft_t ) ; print *, t% altitude
type is ( Missile_t ) ; print *, t% targetID
endselect
enddo
EndProgram