2

我有一个抽象类型和几个继承自他的类型。现在我需要为这些继承类型创建一个实例数组,但我不确定在 Fortran 中是否可行。

我尝试制作一些包装器类型,例如在 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
4

2 回答 2

2

正如 IanH在概述您采用的方法时所评论的那样,gfortran 的当前版本

似乎不支持通过结构构造函数定义无限多态组件

container(b_obj)是这样的事情。因此,撇开您是否仍然遇到这个问题不谈,人们可能对仍然允许旧版本/其他编译器使用代码感兴趣。

另一种方法是不对容器的元素使用构造函数。相反,单个组件可以直接在分配中出现:

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

自然,我们仍然拥有容器类型多态的组件,因此任何引用/定义/等的尝试,该组件都将受到这些各种限制。在您的问题中,您拥有无限多态的组件,但我看到您首先谈到将容器的考虑限制在扩展第一种类型的元素上。与其将容器组件声明为无限多态,不如声明类型更有帮助a

type :: container
    class(a), allocatable :: ptr 
end type

这足以解决问题

do i=1,3
    write(*,*) a_arr(i)%ptr%num
end do

因为numa_arr(i)%ptr(即,a)声明类型的一个组成部分。一般来说,这不是完整的解决方案,因为

do i=1,3
    write(*,*) a_arr(i)%ptr%num_of_type_b
end do

不起作用(使用num_of_type_b扩展类型的组件)。在这里,您必须使用通常的技巧(定义输入/输出、动态分辨率select type等)。这些超出了此答案的范围,可能会发现许多其他问题涵盖它们。

于 2018-06-05T10:31:55.440 回答
1

我添加更正以解决以下错误,

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
于 2020-08-13T11:11:07.837 回答