Fortran 的异构数组 类
Heterogeneous array of Fortran classes
我有一个抽象类型和几个继承自他的类型。现在我需要创建这些继承类型的实例数组,但我不确定在 Fortran 中是否可行。
我尝试制作一些包装类型,例如 。
module m
implicit none
type, abstract :: a
integer, public :: num
end type a
type, extends(a) :: b
end type b
type, extends(a) :: c
end type c
type :: container
class(*), allocatable :: ptr
end type
end module m
program mwe
use m
type(b) :: b_obj
class(*), allocatable :: a_arr(:)
b_obj = b(1)
allocate(container :: a_arr(3))
a_arr(1) = container(b_obj)
end program mwe
但是我收到这个错误:
test3.f90:28:25:
a_arr(1) = container(b_obj)
1
Error: Can't convert TYPE(b) to CLASS(*) at (1)
我做错了什么?或者还有其他正确的方法吗?
尝试 2
我根据 francescalus 的回答编辑了代码:
program mwe
use m
type(b) :: b_obj
type(c) :: c_obj
type(container), allocatable :: a_arr(:)
integer :: i
b_obj = b(1)
c_obj = c(2)
allocate(container :: a_arr(3))
a_arr(1)%ptr = b(1)
a_arr(2)%ptr = c(3)
a_arr(3)%ptr = c(1000)
do i=1,3
write(*,*) a_arr(i)%ptr%num
end do
end program mwe
我收到另一个错误:
test3.f90:36:35:
write(*,*) a_arr(i)%ptr%num
1
Error: ‘num’ at (1) is not a member of the ‘__class__STAR_a’ structure
作为 IanH 在概述您采用的方法时,gfortran 的当前版本
does not appear to support definition of an unlimited polymorphic component via a structure constructor
container(b_obj)
就是这么回事。因此,撇开您是否仍然遇到这个问题不谈,人们可能有兴趣仍然允许旧的 versions/other 编译器使用该代码。
另一种方法是不为容器的元素使用构造函数。相反,单个组件可以直接在作业中显示:
use m
type(container) a_arr(3) ! Not polymorphic...
a_arr%ptr = b(1) ! ... so it has component ptr in its declared type
end mwe
自然地,我们仍然拥有容器类型的多态组件,因此任何 reference/define/etc 的尝试,该组件都将受到各种限制。在你的问题中,你有无限多态的组件,但我看到你首先谈到将容器的考虑限制在扩展第一种类型的元素上。与其将容器组件声明为无限多态,不如声明类型 a
:
更有帮助
type :: container
class(a), allocatable :: ptr
end type
这足以解决
的问题
do i=1,3
write(*,*) a_arr(i)%ptr%num
end do
因为 num
是 a_arr(i)%ptr
声明类型的一个组成部分(即 a
)。一般来说,这不是完整的解决方案,因为
do i=1,3
write(*,*) a_arr(i)%ptr%num_of_type_b
end do
将不起作用(num_of_type_b
扩展类型中的组件)。在这里你必须使用通常的技巧(定义 input/output、动态分辨率、select type
等等)。这些超出了这个答案的范围,可能会发现许多其他问题都涵盖了它们。
我添加更正以解决以下错误,
test3.f90:36:35:
write(*,*) a_arr(i)%ptr%num
1
Error: ‘num’ at (1) is not a member of the ‘__class__STAR_a’ structure
无限多态变量不能直接访问动态数据类型的任何组件。在这种情况下,一个简单的解决方案是避免class(*)
。 container
的定义改为
type :: container
class(a), allocatable :: ptr
end type
所以工作代码总结如下,
module m
implicit none
type, abstract :: a
integer, public :: num
end type a
type, extends(a) :: b
end type b
type, extends(a) :: c
end type c
type :: container
class(a), allocatable :: ptr
end type
end module m
program mwe
use m
type(container), allocatable :: a_arr(:)
integer :: i
allocate(container :: a_arr(3))
a_arr(1)%ptr = b(1)
a_arr(2)%ptr = c(3)
a_arr(3)%ptr = c(1000)
do i=1,3
write(*,*) a_arr(i)%ptr%num
end do
end program mwe
我有一个抽象类型和几个继承自他的类型。现在我需要创建这些继承类型的实例数组,但我不确定在 Fortran 中是否可行。
我尝试制作一些包装类型,例如
module m
implicit none
type, abstract :: a
integer, public :: num
end type a
type, extends(a) :: b
end type b
type, extends(a) :: c
end type c
type :: container
class(*), allocatable :: ptr
end type
end module m
program mwe
use m
type(b) :: b_obj
class(*), allocatable :: a_arr(:)
b_obj = b(1)
allocate(container :: a_arr(3))
a_arr(1) = container(b_obj)
end program mwe
但是我收到这个错误:
test3.f90:28:25:
a_arr(1) = container(b_obj)
1
Error: Can't convert TYPE(b) to CLASS(*) at (1)
我做错了什么?或者还有其他正确的方法吗?
尝试 2
我根据 francescalus 的回答编辑了代码:
program mwe
use m
type(b) :: b_obj
type(c) :: c_obj
type(container), allocatable :: a_arr(:)
integer :: i
b_obj = b(1)
c_obj = c(2)
allocate(container :: a_arr(3))
a_arr(1)%ptr = b(1)
a_arr(2)%ptr = c(3)
a_arr(3)%ptr = c(1000)
do i=1,3
write(*,*) a_arr(i)%ptr%num
end do
end program mwe
我收到另一个错误:
test3.f90:36:35:
write(*,*) a_arr(i)%ptr%num
1
Error: ‘num’ at (1) is not a member of the ‘__class__STAR_a’ structure
作为 IanH
does not appear to support definition of an unlimited polymorphic component via a structure constructor
container(b_obj)
就是这么回事。因此,撇开您是否仍然遇到这个问题不谈,人们可能有兴趣仍然允许旧的 versions/other 编译器使用该代码。
另一种方法是不为容器的元素使用构造函数。相反,单个组件可以直接在作业中显示:
use m
type(container) a_arr(3) ! Not polymorphic...
a_arr%ptr = b(1) ! ... so it has component ptr in its declared type
end mwe
自然地,我们仍然拥有容器类型的多态组件,因此任何 reference/define/etc 的尝试,该组件都将受到各种限制。在你的问题中,你有无限多态的组件,但我看到你首先谈到将容器的考虑限制在扩展第一种类型的元素上。与其将容器组件声明为无限多态,不如声明类型 a
:
type :: container
class(a), allocatable :: ptr
end type
这足以解决
的问题do i=1,3
write(*,*) a_arr(i)%ptr%num
end do
因为 num
是 a_arr(i)%ptr
声明类型的一个组成部分(即 a
)。一般来说,这不是完整的解决方案,因为
do i=1,3
write(*,*) a_arr(i)%ptr%num_of_type_b
end do
将不起作用(num_of_type_b
扩展类型中的组件)。在这里你必须使用通常的技巧(定义 input/output、动态分辨率、select type
等等)。这些超出了这个答案的范围,可能会发现许多其他问题都涵盖了它们。
我添加更正以解决以下错误,
test3.f90:36:35:
write(*,*) a_arr(i)%ptr%num
1
Error: ‘num’ at (1) is not a member of the ‘__class__STAR_a’ structure
无限多态变量不能直接访问动态数据类型的任何组件。在这种情况下,一个简单的解决方案是避免class(*)
。 container
的定义改为
type :: container
class(a), allocatable :: ptr
end type
所以工作代码总结如下,
module m
implicit none
type, abstract :: a
integer, public :: num
end type a
type, extends(a) :: b
end type b
type, extends(a) :: c
end type c
type :: container
class(a), allocatable :: ptr
end type
end module m
program mwe
use m
type(container), allocatable :: a_arr(:)
integer :: i
allocate(container :: a_arr(3))
a_arr(1)%ptr = b(1)
a_arr(2)%ptr = c(3)
a_arr(3)%ptr = c(1000)
do i=1,3
write(*,*) a_arr(i)%ptr%num
end do
end program mwe