抽象类型子例程的数组-Fortran

时间:2019-03-14 15:31:07

标签: oop types fortran gfortran

同样,我可能会对如何(或可以)在Fortran中使用类型感到奇怪。

基本上,到目前为止,我拥有的是具有han界面的抽象类型 AbsBase。现在,我可以多次扩展此类型,从而在子类型上定义sub的不同定义,例如

工作示例


基本模块

module BaseClass

    implicit none

    type, abstract :: AbsBase
    contains
        procedure(subInt), nopass, deferred :: sub
    end type

    interface
        subroutine subInt
            implicit none
        end subroutine subInt
    end interface

end module BaseClass

Child Molude 1

module ChildClass1

    use BaseClass 

    implicit noone

    type, extends(AbsBase) :: Child1
    contains
        procedure, nopass :: sub
    end type

contains

    subroutine sub
        implicit none
        print*, "Do something ..."
    end sub

end module ChildClass1

Child Molude 2

module ChildClass2

    use BaseClass 

    implicit noone

    type, extends(AbsBase) :: Child2
    contains
        procedure, nopass :: sub
    end type

contains

    subroutine sub
        implicit none
        print*, "Do something else ..."
    end sub

end module ChildClass2

程序

program test

    use ChhildClass1
    use ChhildClass2

    implicit none

    type(Child1) :: c1
    type(Child2) :: c2


    call c1%sub    ! <-- prints "Do something ...      "
    call c2%sub    ! <-- prints "Do somethhing else ..."

end program test

到目前为止还不错,但是如果我想定义一个类型的 array 而不是拥有2种不同的 Child 类型呢?我尝试了以下

不工作的例子(我想做什么)


基本模块

module BaseClass

    implicit none

    type, abstract :: AbsBase
    contains
        procedure(subInt), nopass, deferred :: sub
    end type

    interface
        subroutine subInt
            implicit none
        end subroutine subInt
    end interface

    type :: BaseWrap
        class(AbsBase), pointer :: p
    end type

end module BaseClass

程序

program test

    use BaseClass

    implicit none

    type(BaseWrap) :: Child(2) 

    call Child(1)%p%sub   ! <--- This should produce "Do something ..."
    call Child(2)%p%sub   ! <--- This should produce "Do something else ..."

contains

    ! Where to I define the subroutines and how would I do this?

end module ChildClass

它实际上可以编译(这对我来说很令人惊讶),但是显然会导致 Segmentation Fault ,因为我在任何地方都没有定义子例程。如果我理解正确,那么我得到了type(BaseWrap) :: Child(2)的指针数组,这些指针指向抽象类型AbsBase的接口。现在如何从工作示例定义两个子例程?那有可能吗?

谢谢!

2 个答案:

答案 0 :(得分:2)

好吧,您创建的类足以满足您似乎正在寻找的多态行为。您可以像这样测试它:

program test
  use :: BaseClass
  implicit none

  type(Child1), target :: c1
  type(Child2), target :: c2
  type(BaseWrap) :: child(2)

  child(1)%p => c1
  child(2)%p => c2

  call child(1)%p%sub    ! <-- prints "Do something ...      "
  call child(2)%p%sub    ! <-- prints "Do somethhing else ..."
end

但是使用allocatable元素而不是pointer会消除target属性的必要性。

答案 1 :(得分:1)

当那些子例程与类型,我们的数据等有某种联系时,您的设计就很好。您只需要定义Rodrigo显示的指针即可。如果这些子例程实际上不依赖于任何外部类型,而子类型实际上只是使每个子例程持有不同的过程,则您不需要如此复杂的构造。您可以只将过程指针存储为一种类型。

module subs
  implicit none

contains

    subroutine sub1
        print*, "Do something ..."
    end subroutine
    subroutine sub2
        print*, "Do something else ..."
    end subroutine
end module

  use subs

  type sub_wrap
    procedure(sub1), pointer, nopass :: sub
  end type

  type(sub_wrap) :: a(2)

  !one way
  a = [sub_wrap(sub1), sub_wrap(sub2)]

  !another way
!   a(1)%sub => sub1
!   a(2)%sub => sub2

  call a(1)%sub()
  call a(2)%sub()
end