Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Oop 在Fortran中使用多态数据类型的文件IO_Oop_Polymorphism_Fortran_Fortran2003 - Fatal编程技术网

Oop 在Fortran中使用多态数据类型的文件IO

Oop 在Fortran中使用多态数据类型的文件IO,oop,polymorphism,fortran,fortran2003,Oop,Polymorphism,Fortran,Fortran2003,我正在编写一个库,用于将多种类型的几何体(球体、平面、NURBS曲面、stl文件…)导入到scientific Fortran代码中。这类问题似乎是面向对象的,因为定义type::geom然后定义type、extends(geom)::analytic等等很简单。我遇到的问题是文件IO 此时,我的解决方案是编写定义形状的参数,包括一些标志,这些标志告诉我它是哪个形状。在阅读时,我实例化了一个类(geom)::object(因为我事先不知道它将是哪个子类型),但我如何阅读它呢 我无法访问子类型的任

我正在编写一个库,用于将多种类型的几何体(球体、平面、NURBS曲面、stl文件…)导入到scientific Fortran代码中。这类问题似乎是面向对象的,因为定义
type::geom
然后定义
type、extends(geom)::analytic
等等很简单。我遇到的问题是文件IO

此时,我的解决方案是编写定义形状的参数,包括一些标志,这些标志告诉我它是哪个形状。在阅读时,我实例化了一个
类(geom)::object
(因为我事先不知道它将是哪个子类型),但我如何阅读它呢

我无法访问子类型的任何特定组件。我读到下行广播是verboten,而且,新的
分配(subtype::class)
似乎不起作用。新的
读取(格式化)
似乎不是由ifort或gfortran实现的。i、 e

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
我这样做完全错了吗?我可以使用多态性以外的其他方法来解决这个问题,但在其他地方似乎更干净。我们将不胜感激

编辑:使用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

当前gfortran和ifort未实现定义的输入/输出。我没有看到任何证据表明这种情况在不久的将来会发生变化。然而,除了允许一些语法快捷方式之外,这个特性实际上并没有为您节省很多工作

这种情况下的一种方法是为geom的扩展名调用“工厂”,该扩展名使用文件中的数据将参数分配给正确的类型,然后转交给读取特定类型数据的类型绑定过程。例如:

module geom_mod
  implicit none
  integer, parameter :: dp = kind(1.0d0)
  type, abstract :: geom
  contains
    procedure(read_geom), deferred :: read
  end type geom

  abstract interface
    subroutine read_geom(object)
      import :: geom
      implicit none
      class(geom), intent(out) :: object
    end subroutine read_geom
  end interface

  type, extends(geom) :: sphere
    real(dp) :: center(3), radius
  contains
   procedure :: read => read_sphere
  end type sphere
contains
  subroutine read(object)
    class(geom), intent(out), allocatable :: object
    integer :: type
    read (10, *) type
    ! Create (and set the dynamic type of object) based on type.
    select case (type)
    case (1)     ; allocate(sphere :: object)
    case default ; stop 'Unsupported type index'
    end select
    call object%read
  end subroutine read

  subroutine read_sphere(object)
    class(sphere), intent(out) :: object
    read (10, *) object%center, object%radius
  end subroutine read_sphere
end module geom_mod
当前的ifort(12.1.5)在意图(out)多态参数方面存在问题,可能需要解决,但一般方法保持不变


(请注意,子程序读取不是类型绑定子程序-要读取通用几何对象,请在常规子程序引用样式中使用“调用读取(对象)”)

您的输入文件需要(至少)两条记录用于我的示例代码-第一条记录带有类型的整数,第二条记录带有球体数据。你真的得到了一个segfault还是一个文件结束条件?我在sphere类型中添加了一个
integer::type=1
行,这只是混淆了问题。我不知道为什么这会导致seg故障,但当我坚持使用您的模块时,它会正常工作。谢谢似乎seg故障与派生类型中具有默认值的任何变量有关。因此,如果我在类型定义中设置
radius=1
,我会得到seg错误。您是否使用英特尔Fortran 12.x?如果是这样的话,这听起来像是我提到的意图(OUT)多态性参数的问题。带有默认初始化或可分配组件的参数基本上总是需要输入输出。考虑到早期发行说明,13.0可能会修复。我正在使用ifort-V12.1。我可以看到默认值是如何进入数据的,因此意图应该是INOUT。再次感谢。