2017-05-16 24 views
2

タイプ定義にfinalキーワードを使用して、Fortranでオブジェクトデストラクタを記述しています。しかし、デストラクタは、それらのインスタンスの配列がスコープを離れるとき呼び出されません。この例のモジュールで配列の最終ルーチンを呼び出す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が適切に分解され、multiple_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オブジェクトの配列、その状況に依存しません。デストラクタでオブジェクトの配列が必要な場合は、コンテナオブジェクトで間接性のレイヤーを追加することで修正できます。それは入れ子になった%構成やポインタの束を必要とし、不器用に思えます。配列を強制的に破壊するよりエレガントな方法はありますか?

+0

'allocate'と' deallocate'はメモリ内の配列を初期化し( 'source'引数が' allocate'で指定されているとき)、メモリから配列を削除するのに役立ちます( 'deallocate')。 –

+0

使用しているコンパイラとコンパイラのバージョンは重要です。 –

+1

GNU Fortran(Debian 4.9.2-10)4.9.2とifort(IFORT)14.0.2の結果は同じです。20140120 –

答えて

4

最終的なサブルーチンは、スカラーと終了する型の配列の各ランクに対して指定する必要があります。例:

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 

(私も単体での書き込みを使用する可能性を持っている不純を追加しました手順)。

最新のコンパイラを使用することを強くお勧めします。 finalの完全実装は古いコンパイラでは利用できない場合があります。

関連する問題