多态父类型

时间:2016-03-17 12:49:02

标签: oop fortran derived-types type-bounds

我正在尝试设置Fortran OOP代码,其中父类型geom具有可分配字段shape。此字段分配有geom的扩展类型之一,即circlerectangle类型。在另一个模块中,我有body类型,其中包含geom字段。

所以基本上我想要一个geom类型,它实际上可以访问不同类型(然后根据类型访问不同的字段)和body类型,它是用几何体初始化的。

找到下面的代码。这是几何的模块:

module geomMod

  implicit none

  type :: geom
    class(*),allocatable  :: shape
  contains
    procedure,private     :: set_geom
    generic               :: assignment(=) => set_geom
  end type geom

  type,extends(geom) :: circle
    integer :: id=1
    real    :: centre(2)
    real    :: radius
  end type circle

  type,extends(geom) :: rectangle
    integer :: id=2
    real    :: centre(2)
    real    :: length(2)
  end type rectangle

contains

  subroutine set_geom(a,b)
    implicit none
    class(geom),intent(inout) :: a
    class(*),intent(in)    :: b

    allocate(a%shape,source=b)
  end subroutine set_geom

end module geomMod

这是身体的模块:

module bodyMod
  use geomMod
  implicit none

  type :: body
    class(geom),allocatable :: geom1
    real,allocatable        :: x(:,:)           
    integer                 :: M=50            
    real                    :: eps=0.1         
  contains
    procedure :: init
  end type body

contains

  subroutine init(a,geom1,M,eps)
    implicit none

    class(body),intent(inout)   :: a
    class(geom),intent(in)      :: geom1
    integer,intent(in),optional :: M
    real,intent(in),optional    :: eps

    allocate(a%geom1,source=geom1)

    if(present(M)) a%M = M
    if(present(eps)) a%eps = eps
    if(.not.allocated(a%x)) allocate(a%x(a%M,2))
  end subroutine init

end module bodyMod

这就是我从主文件初始化它们的方式:

  use bodyMod
  implicit none

  integer,parameter :: M = 500
  real,parameter    :: eps = 5

  type(body) :: b
  type(geom) :: geom1

  geom1 = circle(centre=(/1,1/),radius=0.5)

  call b%init(geom1=geom1,M=M,eps=eps)

但是我使用gfortran 4.8.4编译此错误。

  geom1 = circle(centre=(/1,1/),radius=0.5)
          1
Error: No initializer for component 'shape' given in the structure constructor at (1)!

1 个答案:

答案 0 :(得分:1)

您的结构构造函数circle仅使用指定的两个组件的值引用

geom1 = circle(centre=(/1,1/),radius=0.5)

并且您的编译器不喜欢它。

circle类型有四个组成部分,shapeidcentreradius。在引用结构构造函数时,并不总是需要为所有组件赋值,这里有两种情况适用。

第一种情况是组件具有默认初始化。您和您一样,完全有权省略组件id的值。

第二种情况是可分配组件。这就是问题所在:规则在Fortran 2003和Fortran 2008标准之间发生了变化。

在Fortran 2008下,允许省略与可分配组件对应的值。在Fortran 2003中,它不是。

您的编译器错误表明它在这方面遵循Fortran 2003的规则,并且它需要可分配组件shape的值。 gfortran是such a compiler

要提供此类值,请保留组件未分配,可以

geom1 = circle(shape=NULL(),centre=(/1,1/),radius=0.5)