我正在尝试设置Fortran OOP代码,其中父类型geom
具有可分配字段shape
。此字段分配有geom
的扩展类型之一,即circle
或rectangle
类型。在另一个模块中,我有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)!
答案 0 :(得分:1)
您的结构构造函数circle
仅使用指定的两个组件的值引用
geom1 = circle(centre=(/1,1/),radius=0.5)
并且您的编译器不喜欢它。
circle
类型有四个组成部分,shape
,id
,centre
和radius
。在引用结构构造函数时,并不总是需要为所有组件赋值,这里有两种情况适用。
第一种情况是组件具有默认初始化。您和您一样,完全有权省略组件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)