简体   繁体   English

Fortran 类的异构数组

[英]Heterogeneous array of Fortran classes

I have an abstract type and several types which inherit from him.我有一个抽象类型和几个继承自他的类型。 Now I need to make an array of instances of those inherited types, but I'm not sure, if it's even possible in Fortran.现在我需要制作这些继承类型的实例数组,但我不确定,在 Fortran 中是否可能。

I've tried to make some wrapper type, like in Creating heterogeneous arrays in 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 

But I'm getting this error:但我收到此错误:

test3.f90:28:25:

 a_arr(1) = container(b_obj)
                     1
Error: Can't convert TYPE(b) to CLASS(*) at (1)

What am I doing wrong?我究竟做错了什么? Or is there any other, correct way to do it?或者有没有其他正确的方法来做到这一点?


Attempt 2尝试 2

I edited the code accordingly to francescalus's answer:我根据 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 

And I'm getting another error:我收到另一个错误:

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

As IanH commented when outlining the approach you take, the then current version of gfortran正如 IanH 在概述您采用的方法时所评论的那样,当时的 gfortran 版本

does not appear to support definition of an unlimited polymorphic component via a structure constructor似乎不支持通过结构构造函数定义无限多态组件

container(b_obj) is such a thing. container(b_obj)就是这样的东西。 So, leaving aside whether you are still coming up against this problem, one may be interested in still allowing older versions/other compilers to use the code.因此,不管您是否仍然遇到这个问题,人们可能对仍然允许旧版本/其他编译器使用代码感兴趣。

An alternative approach is not to use a constructor for the element of your container.另一种方法是不对容器的元素使用构造函数。 Instead the single component can feature directly in an assignment:相反,单个组件可以直接在作业中使用:

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

Naturally, we still have the component of the container type polymorphic so any attempts to reference/define/etc., that component will be subject to those various restrictions.自然地,我们仍然有容器类型多态的组件,因此任何引用/定义/等的尝试,该组件都将受到各种限制。 In your question you have the component unlimited polymorphic, but I see that you first talk about restricting the container's consideration to elements which extend the first type.在您的问题中,您拥有无限多态的组件,但我看到您首先谈到将容器的考虑限制为扩展第一种类型的元素。 Rather than declaring the container component as unlimited polymorphic it could be much more helpfully of declared type a :与其将容器组件声明为无限多态,不如声明类型a更有帮助:

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

This would be sufficient to solve the problem with这足以解决问题

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

because num is a component of the declared type of a_arr(i)%ptr (that is., a ).因为num是声明类型中的一个分量a_arr(i)%ptr (即, a )。 In general, it isn't the complete solution because一般来说,这不是完整的解决方案,因为

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

wouldn't work (with num_of_type_b a component in the extending type).不起作用(使用num_of_type_b扩展类型中的组件)。 Here you have to use the usual tricks (defined input/output, dynamic resolution, select type and so on).在这里,您必须使用通常的技巧(定义的输入/输出、动态分辨率、 select type等)。 Those are beyond the scope of this answer and many other questions may be found covering them.这些超出了本答案的范围,可能会发现许多其他问题涵盖它们。

I add the correction to resolve the following error,我添加更正以解决以下错误,

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

The unlimited polymorphic variable cannot directly access any component of the dynamic data type.无限多态变量不能直接访问动态数据类型的任何组件。 In this case, a simple solution is to avoid class(*) .在这种情况下,一个简单的解决方案是避免class(*) The definition of container is changed to container的定义改为

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

So the working code in summary is as follows,所以总结起来的工作代码如下,

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM