Fortran在数组上调用最终例程

时间:2017-05-16 08:14:07

标签: arrays oop fortran

我正在使用类型定义中的final关键字在Fortran中编写对象析构函数。但是当这些实例的数组离开范围时,不会调用析构函数。

module problem_module

  type :: destructable_object
    integer :: nr
  contains
    final :: destruct
  end type destructable_object

  type :: collection
    type(destructable_object) :: single_member
    type(destructable_object), dimension(3) :: multiple_members
  end type collection

contains

  subroutine destruct(instance)
    type(destructable_object), intent(in) :: instance
    write(*,*) "Destruct ",instance%nr
  end subroutine destruct

end module problem_module

在此示例模块中,destructable_object类型的任何标量都将使用final关键字引发的破坏例程进行解构。但是,destructable_object类型的数组不会被解构。对于其他类中的destructable个对象,如果它们是标量,也只能被正确地解构(在这个例子中,single_member被正确地解构,而multi_members则没有)。这与包含对象是否在数组中无关。所以,例如

program main

  ! Destructors are only called at end of subroutines, not at the end     of the program.
  ! Therefore, I move the entire program to a subroutine.
  call main_execute

contains

  subroutine main_execute

    use problem_module

    implicit none

    type(destructable_object) :: single_instance
    type(destructable_object), dimension(3) :: multiple_instances
    type(collection) :: single_collection
    type(collection), dimension(3) :: multiple_collections

    single_instance%nr = 1
    multiple_instances(1)%nr = 2
    multiple_instances(2)%nr = 3
    multiple_instances(3)%nr = 4
    single_collection%single_member%nr = 5
    single_collection%multiple_members(1)%nr = 6
    single_collection%multiple_members(2)%nr = 7
    single_collection%multiple_members(3)%nr = 8
    multiple_collections(1)%single_member%nr = 9
    multiple_collections(1)%multiple_members(1)%nr = 10
    multiple_collections(1)%multiple_members(2)%nr = 11
    multiple_collections(1)%multiple_members(3)%nr = 12
    multiple_collections(2)%single_member%nr = 13
    multiple_collections(2)%multiple_members(1)%nr = 14
    multiple_collections(2)%multiple_members(2)%nr = 15
    multiple_collections(2)%multiple_members(3)%nr = 16
    multiple_collections(3)%single_member%nr = 17
    multiple_collections(3)%multiple_members(1)%nr = 18
    multiple_collections(3)%multiple_members(2)%nr = 19
    multiple_collections(3)%multiple_members(3)%nr = 20

  end subroutine main_execute

end program main

返回

Destruct            1
Destruct            5
Destruct            9
Destruct           13
Destruct           17

destructable对象的所有标量实例,而不是destructable对象的数组,与其情况无关。如果我想要一个带析构函数的对象数组,我可以通过在容器对象中添加一个间接层来解决这个问题。这看起来很笨拙,需要嵌套的%-constructions或一堆指针。是否有更优雅的方法来强制销毁数组?

1 个答案:

答案 0 :(得分:4)

必须为标量和要完成的类型数组的每个等级指定不同的最终子例程。 E.g:

module problem_module

  type :: destructable_object
    integer :: nr
  contains
    final :: destruct, destruct_array
  end type destructable_object

  type :: collection
    type(destructable_object) :: single_member
    type(destructable_object), dimension(3) :: multiple_members
  end type collection

contains

  subroutine destruct(instance)
    type(destructable_object), intent(in) :: instance
    write(*,*) "Destruct ",instance%nr
  end subroutine destruct

  subroutine destruct_array(instance)
    type(destructable_object), intent(in) :: instance(:)
    write(*,*) "Destruct array ",instance%nr
  end subroutine destruct_array

end module problem_module

为避免多重定义,您可以将元素属性添加到子例程中:

module problem_module

  type :: destructable_object
    integer :: nr
  contains
    final :: destruct
  end type destructable_object

  type :: collection
    type(destructable_object) :: single_member
    type(destructable_object), dimension(3) :: multiple_members
  end type collection

contains

  impure elemental subroutine destruct(instance)
    type(destructable_object), intent(in) :: instance
    write(*,*) "Destruct ",instance%nr
  end subroutine destruct

end module problem_module

(我还添加了 impure 以便在元素过程中使用写入)。

我强烈建议使用更新的编译器。旧编译器可能无法完全实现 final 内容。