Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.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中分配和构造多态对象的规范方法是什么?_Oop_Constructor_Fortran_Polymorphism - Fatal编程技术网

Oop Fortran中分配和构造多态对象的规范方法是什么?

Oop Fortran中分配和构造多态对象的规范方法是什么?,oop,constructor,fortran,polymorphism,Oop,Constructor,Fortran,Polymorphism,我想创建一个多态对象数组,它的构造函数根据其动态类型采用不同的伪参数。阅读了有关用户定义和结构构造函数的内容后,我认为没有办法将这些概念应用于动态分配的对象。在C++背景下,我习惯于在动态或堆栈中分配对象时可以使用同一个构造函数“成员函数”,但是如何在分配的对象上显式调用用户定义的FORTRAN构造函数? 相反,我尝试处理泛型和类型绑定的init函数: module mod type :: basis_t contains procedure, public :: init_func =

我想创建一个多态对象数组,它的构造函数根据其动态类型采用不同的伪参数。阅读了有关用户定义和结构构造函数的内容后,我认为没有办法将这些概念应用于动态分配的对象。在C++背景下,我习惯于在动态或堆栈中分配对象时可以使用同一个构造函数“成员函数”,但是如何在分配的对象上显式调用用户定义的FORTRAN构造函数? 相反,我尝试处理泛型和类型绑定的init函数:

module mod
type :: basis_t
contains
    procedure, public :: init_func => init_base
    ! I want a generic constructor function
    generic, public   :: init => init_func 
end type

type, extends(basis_t) :: extended_t
contains
    ! cannot work, init_extended has a different signature from init_base
    procedure, public :: init => init_extended 
end type

type wrapper_t
   type(basis_t), pointer :: obj
end type

contains
   subroutine init_base(this)
      class(base_t), intent(inout) :: this
   end subroutine

   subroutine init_extended(this, param)
      class(extended_t), intent(inout) :: this
      integer :: param
   end subroutine
end module

program
   use mod
   implicit none

   type(wrapper_t) :: arr(2)
   allocate(basis_t::arr(1)%obj)
   allocate(extended_t::arr(2)%obj)
   call arr(1)%obj%init    ! calls init_basis
   call arr(2)%obj%init(4) ! calls init_extended
end program
但是我不相信我是在正确的轨道上,比如在C++中,我宁愿做< < /P> >
basis_t* arr[2];
arr[0] = new basis_t;
arr[1] = new extended_t{ 4 };

<> P>重要区别是C++中的构造函数是<强> > < /强>类型绑定/虚,如我的FORTRAN方法。我能做什么?

Fortran中构造函数的角色可以通过以下方式提供:

  • 该语言提供了结构构造函数

  • 一种函数,其结果属于所构造对象的类型。该语言允许泛型函数与派生类型具有相同的名称,并进一步允许对此类函数的引用重载对该类型的结构构造函数的引用

  • 定义适当类型的intent(out)参数的子例程

你使用什么在一定程度上取决于环境和个人喜好。在某些情况下,语言提供的结构构造函数可以在常量表达式中使用,但只允许组件的简单值定义(无可执行代码);函数引用表单允许您作为对象构造的一部分执行任意代码,不能在常量表达式中使用,不能轻易指示构造失败,并且如果构造的对象很大,可能会很昂贵(取决于Fortran处理器的实现细节);子例程窗体需要单独的call语句(构造函数不能是较大表达式的一部分),并且不能利用泛型名称/结构重载语言功能

这三种方法都不涉及类型绑定过程。在某些情况下,类型绑定过程可能适用于对象定义(例如,类型绑定过程旨在从文件中读取对象值-扩展层次结构中的所有类型都需要传递给它们的有关文件的相同信息),但对于构造而言,这并没有一般意义,定义对象的类型以及对象的值

Fortran中的指针主要用于引用语义(因为它们是引用)。如果您想要值语义,通常不想使用它们-使用allocatables

TYPE :: ta
  INTEGER :: a
END TYPE ta

TYPE, EXTENDS(ta) :: tb
  REAL :: b
END TYPE :: tb

INTERFACE tb
  PROCEDURE :: tb_construct
END INTERFACE tb

TYPE, EXTENDS(ta) :: tc
END TYPE tc

TYPE :: ta_item
  CLASS(ta), ALLOCATABLE :: item
END TYPE ta_item

!...

FUNCTION tb_construct(arg)
  INTEGER, INTENT(IN) :: arg
  TYPE(tb) :: tb_construct
  tb_construct%a = arg + 1
  tb_construct%b = arg / 2.0
END FUNCTION tb_construct

SUBROUTINE ConstructTC(obj, arg, stat)
  CLASS(ta), INTENT(OUT), ALLOCATABLE :: obj
  INTEGER, INTENT(IN) :: arg
  INTEGER, INTENT(OUT) :: stat
  TYPE(tc), ALLOCATABLE :: tmp
  IF (arg < 0) THEN
    ! Construction failed.
    stat = 1
    RETURN
  END IF
  tmp%a = arg + 4
  CALL MOVE_ALLOC(tmp, obj)
  stat = 0    ! Construction succeeded.
END SUBROUTINE ConstructTC

!...

TYPE(ta_item) :: the_items(3)
INTEGER :: stat

! Structure constructor
the_items(1)%item = ta(1)

! Overloaded function.
the_items(2)%item = tb(2)

! Subroutine.
CALL ConstructTC(the_items(3)%item, 3, stat)
IF (stat /= 0) ERROR STOP 'It failed.'
TYPE::ta
整数::a
端型ta
类型,扩展(ta)::tb
真的吗
结束类型::tb
接口tb
过程::tb_构造
终端接口tb
类型,扩展(ta)::tc
端型tc
类型::ta_项目
类(ta),可分配::项
终端类型ta_项目
!...
函数tb_构造(arg)
整数,意图(IN)::arg
类型(tb)::tb\U构造
tb_构造%a=arg+1
tb_构造%b=arg/2.0
端函数tb_构造
子例程constructC(obj、arg、stat)
类(ta)、意图(OUT)、可分配::obj
整数,意图(IN)::arg
整数,意图(输出)::stat
类型(tc),可分配::tmp
如果(arg<0),则
! 建设失败了。
stat=1
返回
如果结束
tmp%a=arg+4
呼叫移动分配(tmp、obj)
统计=0!施工成功。
结束子例程constructC
!...
类型(ta_项)::_项(3)
整数::stat
! 结构构造器
_项(1)%item=ta(1)
! 重载函数。
_项目(2)%item=tb(2)
! 子程序。
调用ConstructTC(项目(3)%item,3,stat)
如果(stat/=0)错误,请停止“它失败”

谢谢你富有启发性的回答,这正好满足了我的需要。但是,虽然我可以使用GCC的gfortran编译此代码,但英特尔编译器ifort 16.0.0(我绑定到它)将抛出诊断
错误#8304:在内部赋值语句中,变量不应是多态的。[ITEM]_items(1)%ITEM=ta(1)
错误#6197:不同结构类型的赋值无效。_items(2)%item=tb(2)
。我确信在某个时候我已经尝试过你的方法,但是偶然发现了这个问题,没有意识到这是一个编译器错误。有什么想法吗?对多态可分配函数的内在赋值是F2008的一个特性,在该版本的编译器中不可用(19.0是最新版本,20.0即将发布)。如果您使用结构构造函数或函数来构造对象,请使用ALLOCATE语句的源说明符,即
ALLOCATE(the_items(1)%item,SOURCE=ta(…)