在Fortran中分配和构造多态对象的规范方法是什么? [英] What is the canonical way to allocate and construct polymorphic objects in Fortran?

查看:67
本文介绍了在Fortran中分配和构造多态对象的规范方法是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想创建一个多态对象数组,这些对象的构造函数根据其动态类型采用不同的伪参数.阅读了有关用户定义和结构构造函数的文章之后,我看不到将这些概念应用于动态分配的对象的方法.在C ++中有背景,我习惯于在动态分配或在堆栈上分配对象时可以使用一个相同的构造函数成员函数",但是如何在分配的对象上显式调用用户定义的Fortran构造函数呢?

I want to create an array of polymorphic objects which have constructors taking different dummy arguments depending on their dynamic type. Having read about user-defined and structure constructors, I see no way to apply these concepts to dynamically allocated objects. Having a background in C++, I was used to the notion that I could use one and the same constructor "member function" when allocating objects either dynamically or on the stack, but how can I explicitly call user-defined Fortran constructors on allocated objects?

相反,我尝试摆弄泛型和类型绑定的init函数:

Instead, I tried to fiddle with generic and type-bound init functions:

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 ++我更愿意这样做

But I don't believe that I am on the right track, as in e.g. C++ I would rather do e.g.

basis_t* arr[2];
arr[0] = new basis_t;
arr[1] = new extended_t{ 4 };

重要的区别是C ++中的构造函数不是不是类型绑定/虚拟的,就像我的Fortran方法一样.我该怎么办?

The important difference is that the constructors in C++ are not type-bound/virtual, as in my Fortran approach. What can I do?

推荐答案

在Fortran中,构造函数的作用可以由以下方式提供:

The role of a constructor in Fortran can be provided by:

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

一个函数,其结果与正在构造的对象的类型相同.该语言允许泛型函数与派生类型具有相同的名称,并进一步允许对该函数的引用来重载否则将引用该类型的结构构造函数的方法.

A function with a result that is of the type of the object being constructed. The language allows a generic function to have the same name as a derived type, and further allows a reference to such a function to overload what would otherwise be a reference to a structure constructor for the type.

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

A subroutine that defines an intent(out) argument of the appropriate type.

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

What you use depends on circumstances and personal preference to an extent. The language provided structure constructor can be used in constant expressions in some circumstances, but only permits simple value definition of components (no executable code); the function reference form permits you to execute arbitrary code as part of object construction, cannot be used in constant expressions, cannot easily indicate construction failure and might be expensive (depending on Fortran processor implementation details) if the constructed object is large; the subroutine form requires a separate call statement (the constructor cannot be part of a larger expression) and cannot take advantage of the generic name/structure overload language feature.

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

None of those three methods involve a type bound procedure. There are some circumstances where a type bound procedure might be appropriate for object definition (a type bound procedure intended to read an object value from a file, for example - all types in the extension hierarchy require the same information about the file to be passed to them), but it doesn't make general sense for construction, where you are defining the type of the object as well as defining its value.

Fortran中的指针主要用于引用语义(因为它们是引用).如果需要值语义,通常不希望使用它们-使用可分配的表.

Pointers in Fortran are mostly used for reference semantics (because they are references). You generally do not want to use them if you want value semantics - use 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.'

这篇关于在Fortran中分配和构造多态对象的规范方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆