Fortran 中继承派生类型问题的可分配数组
Allocatable Array of Inherited Derived Types Issues in Fortran
我正在尝试创建一组派生类型的全局可用可分配数组,这些派生类型与单个对象共享继承。 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
以上只是在没有编译器的计算机上编写的示例代码。我已尽力而为,希望即使有错别字也很少。我尽量模仿原代码的结构。
问题是字段 "objects%trajTable" 在离开 "objectsInit" 子例程后返回到未定义的指针。时间、id 和 currPos 等其他值仍然正确。我该如何纠正?
我正在使用 Visual Studio 2012 和 Intel Visual Fortran 2015。
因为程序有很多重叠的名称(比如 Aircraft 和 aircraft,在 Fortran 中被认为是相同的),我在所有类型上都附加了“_t”(例如 Aircraft 到 Aircraft_t 等)和所有模块名称的“_m”(例如,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
我正在尝试创建一组派生类型的全局可用可分配数组,这些派生类型与单个对象共享继承。 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
以上只是在没有编译器的计算机上编写的示例代码。我已尽力而为,希望即使有错别字也很少。我尽量模仿原代码的结构。
问题是字段 "objects%trajTable" 在离开 "objectsInit" 子例程后返回到未定义的指针。时间、id 和 currPos 等其他值仍然正确。我该如何纠正?
我正在使用 Visual Studio 2012 和 Intel Visual Fortran 2015。
因为程序有很多重叠的名称(比如 Aircraft 和 aircraft,在 Fortran 中被认为是相同的),我在所有类型上都附加了“_t”(例如 Aircraft 到 Aircraft_t 等)和所有模块名称的“_m”(例如,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