Я пишу библиотеку для импорта геометрий многих типов (сфер, плоскостей, поверхностей NURBS, stl-файлов ...) в научный код Fortran. Подобная проблема кажется сложной для ООП, потому что просто определить type :: geom
, а затем type,extends(geom) :: analytic
и так далее. У меня есть проблема с файлом IO.Файл IO с использованием полиморфных типов данных в Fortran
Мое решение на данном этапе состоит в том, чтобы написать параметры, определяющие фигуры, в том числе некоторые флаги, которые говорят мне, какая форма. Когда я читаю, я создаю экземпляр class(geom) :: object
(так как я не знаю заранее, какой подтип будет), но как я могу его прочитать?
Я не могу получить доступ к каким-либо конкретным компонентам подтипа. Я читал, что downcasting verboten, и, кроме того, новый allocate(subtype :: class)
не работает. Новый READ(FORMATTED)
, похоже, не реализован ifort или gfortran. то есть
module geom_mod
type :: geom
end type
type,extends(geom) :: sphere
integer :: type
real(8) :: center(3),radius
contains
generic :: READ(FORMATTED)=> read_sphere ! not implemented anywhere
end type
contains
subroutine read_geom(object)
class(geom),intent(out),pointer :: object
integer :: type
read(10,*) object%type ! can't access the subtype data yet
read(10,*) type
backspace(10)
if(type==1) then
allocate(sphere :: object)! downcast?
read(10,*) object ! doesn't work
end if
end read_geom
end module
Я все об этом не так? Я мог бы взломать это, используя что-то другое, кроме полиморфизма, но это кажется чище везде. Помощь была бы весьма признательна.
EDIT: пример программы с использованием модуля IanH в
program test
use geom_mod
implicit none
class(geom),allocatable :: object
open(10)
write(10,*) '1'
write(10,*) sphere(center=0,radius=1)
rewind(10)
call read(object) ! works !
end program test
Вашего входного файла должен иметь (по крайней мере) две записи для моего примера кода - первая запись с целым числом для типа, вторая с данными сферы. Вы действительно получаете segfault или это состояние конца файла? – IanH
Я добавил в тип сферы строку 'integer :: type = 1', которая просто путала проблему. Я не знаю, почему это приводит к ошибке seg, но когда я придерживаюсь вашего модуля как есть, он работает. Благодаря! – weymouth
Кажется, что seg fault связан с наличием каких-либо переменных в производном типе со значениями по умолчанию. Поэтому, если я устанавливаю «radius = 1» в определении типа, я получаю ошибку seg. – weymouth