在 Fortran 中存储“函数指针”?

Ste*_*ini 4 fortran function-pointers

在 Fortran 中,您可以将函数/子例程 A 作为参数传递给另一个函数/子例程 B,但是您能否存储 A 以供以后检索和使用?

例如,这在 C 中是允许的

int foo(float, char, char) { /*whatever*/};

int (*pointerToFunction)(float, char, char);
pointerToFunction = foo;
Run Code Online (Sandbox Code Playgroud)

在 Fortran 中,您可以将子程序作为参数传递

subroutine foo
! whatever
end subroutine foo

subroutine bar(func)
    call func
end subroutine bar

program x

    call bar(foo)

end program
Run Code Online (Sandbox Code Playgroud)

但是如何以与 C 类似的方式存储 foo 的地址?

Wil*_*cat 5

从所谓的“Fortran 2003”(ISO/IEC 1539-2004)开始,过程指针是 Fortran 语言的一部分。这绝对是 Fortran 语言的主要新特性。

Fortran Wiki 中的用法示例


Stefano,你提到了策略设计模式。在 Fortran 2003 中,您可以使用纯 OOP 方式来实现它(没有过程指针)。副手示例:

策略.f90

module strategies

  implicit none

  private

  public :: strategies_transportation_strategy, &
            strategies_by_taxi_strategy, &
            strategies_by_bus_strategy

  type, abstract :: strategies_transportation_strategy
  contains
    procedure(transportation_strategy_go), deferred :: go
  end type strategies_transportation_strategy

  type, extends(strategies_transportation_strategy) :: strategies_by_taxi_strategy
  contains
    procedure :: go => strategies_by_taxi_strategy_go
  end type strategies_by_taxi_strategy

  type, extends(strategies_transportation_strategy) :: strategies_by_bus_strategy
  contains
    procedure :: go => strategies_by_bus_strategy_go
  end type strategies_by_bus_strategy

  abstract interface
    subroutine transportation_strategy_go(this)
      import strategies_transportation_strategy
      class(strategies_transportation_strategy), intent(in) :: this
    end subroutine transportation_strategy_go
  end interface

  contains

    subroutine strategies_by_taxi_strategy_go(this)
      class(strategies_by_taxi_strategy), intent(in) :: this

      print *, "We are using taxi."

    end subroutine strategies_by_taxi_strategy_go

    subroutine strategies_by_bus_strategy_go(this)
      class(strategies_by_bus_strategy), intent(in) :: this

      print *, "We are using public transport."

    end subroutine strategies_by_bus_strategy_go

end module strategies
Run Code Online (Sandbox Code Playgroud)

车辆.f90

module vehicles

  use strategies

  implicit none

  private

  public :: vehicles_vehicle, &
            vehicles_taxi, &
            vehicles_bus

  type, abstract :: vehicles_vehicle
    private
    class(strategies_transportation_strategy), allocatable :: transportation_strategy
  contains
    procedure :: set_transportation_strategy => vehicle_set_transportation_strategy
    procedure :: go => vehicle_go
  end type vehicles_vehicle

  type, extends(vehicles_vehicle) :: vehicles_taxi
  contains
    procedure :: init => taxi_init
  end type vehicles_taxi

  type, extends(vehicles_vehicle) :: vehicles_bus
  contains
    procedure :: init => bus_init
  end type vehicles_bus

  contains

    subroutine vehicle_go(this)
      class(vehicles_vehicle), intent(in) :: this

      call this%transportation_strategy%go()

    end subroutine vehicle_go

    subroutine vehicle_set_transportation_strategy(this, new_transportation_strategy)
      class(vehicles_vehicle), intent(inout) :: this
      class(strategies_transportation_strategy), intent(in) :: new_transportation_strategy

      if (allocated(this%transportation_strategy)) then
        deallocate (this%transportation_strategy)
      end if

      allocate (this%transportation_strategy, source=new_transportation_strategy)

    end subroutine vehicle_set_transportation_strategy

    subroutine taxi_init(this)
      class(vehicles_taxi), intent(out) :: this

      type(strategies_by_taxi_strategy) :: by_taxi_strategy

      call this%set_transportation_strategy(by_taxi_strategy)

    end subroutine taxi_init

    subroutine bus_init(this)
      class(vehicles_bus), intent(out) :: this

      type(strategies_by_bus_strategy) :: by_bus_strategy

      call this%set_transportation_strategy(by_bus_strategy)

    end subroutine bus_init

end module vehicles
Run Code Online (Sandbox Code Playgroud)

main.f90

program main

  use vehicles

  implicit none

  type(vehicles_taxi) :: taxi
  type(vehicles_bus) :: bus

  call taxi%init()
  call bus%init()

  call taxi%go()
  call bus%go()

end program main
Run Code Online (Sandbox Code Playgroud)

至少可以使用 gfortran 4.6 (20100925) 工作。