【问题标题】:Array of abstract type subroutines - Fortran抽象类型子例程数组 - Fortran
【发布时间】:2019-03-14 15:31:07
【问题描述】:

关于我将如何(或可以)在 Fortran 中使用类型,我可能有一个奇怪的问题。

基本上,到目前为止我所拥有的是一个 抽象类型 AbsBase 与 han 接口。我现在可以通过定义 Child types 多次扩展此类型,其中我对 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

儿童莫鲁德 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

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

谢谢!

【问题讨论】:

  • 感谢您的快速回复!抱歉,我不明白这将如何解决我的问题?这是否意味着我想做的事情是不可能的?
  • 不,你实际上已经在做那里描述的事情,我对你的类型名称 Base 感到困惑,这实际上不是扩展的基础。这就是链接所描述的包装器。
  • 但在那种情况下,我不明白这个问题。当您添加最后一部分时,发生了什么?当您实际分配指针时(尽管我建议使用可分配的),它应该可以正常工作。不过,您也可以在 Base 类中有一个过程指针,您可以完全摆脱 AbsClass
  • 那么,如果我做对了,我将如何在使用 Base 类型时定义我的sub?我的意思是我不能做类似type, extend(Child(1)%p) :: c 的事情,然后为每个数组索引(Child(1)、Child(2))定义sub
  • 对不起,我真的不明白你的主要段落。有些术语以一种令人困惑的方式组合在一起。什么是“子程序接口”?什么是“通过数组索引覆盖子程序”?您不只是想要一个过程指针数组吗?因为否则我真的不明白你的最终意图是什么,我担心我们正在解决XY problem

标签: oop types fortran gfortran


【解决方案1】:

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

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 属性的必要性以及其他优点。

【讨论】:

  • 谢谢!看来这将回答我的问题。我将在当天晚些时候对此进行测试。
【解决方案2】:

当这些子程序以某种方式与类型、我们的数据等紧密相关时,您的设计是好的。您只需要像 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

【讨论】:

  • @marc_s 我不太了解您的编辑。为什么用分词而不是现在时?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多