Я пытаюсь настроить код Оранга Fortran, где родительский тип 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)!
gfortran 4.8.4. С этим тегом я просто имею в виду, что я кодирую стиль F2003 OOP вместо F90. Но я удаляю его, так как это может ввести в заблуждение. –
Я ответил, основываясь на разрешении сообщения об ошибке, но я не совсем уверен, что следую вашему намеченному дизайну. Наличие типа расширения имеет унаследованный компонент, который вы намереваетесь выделить динамическим типом расширяющегося типа, который меня смущает.Однако я не внимательно следил за вашим предыдущим вопросом по этой теме, поэтому я, возможно, что-то пропустил. Все, что я говорю, я собираюсь ответить на вопрос об ошибке, а не комментировать аспекты дизайна. – francescalus
Не проще ли изменить «geom» как пустой базовый класс и просто выполнить «вызов b% init (circle (center = [1.0,1.0], radius = 0.5)), M = M, eps = eps) "? (потому что «тело» уже имеет «класс (geom), allocatable», который кажется достаточным для хранения информации геометрии.) – roygvib