1

以下の最小限の作業例を考えると、呼び出しのコピー/貼り付けを避けるために変更したいと思います

call func_some_calc1(par)
call func_some_calc2(par)

と の両方main_func_problem1main_func_problem2。理想的には、タイプおよびmain_funcの入力パラメーターに対して異なる動作をする 1 つの関数が必要です。基本型のパラメーターを宣言することはできますが、実際の引数の型に応じてその関数内にスイッチを (を使用して) 持つことは、アーキテクチャ上良くありません。t_parameters_problem1t_parameters_problem2parclass(t_parameters_base)select type

これを解決するために、これらのルーチンを呼び出すprocedurein typeを作成してt_parameters_base、次のようなものを実装しようとしました (C++ 構文):

class t_parameters_base {
  virtual void main_func() {
    func_some_calc1(this)
    func_some_calc2(this)
  }
}
class t_parameters_problem1: public t_parameters_base {
  virtual void main_func() {
    t_parameters_base::main_func();
    func_some_calc3_problem1(this);
  }
}

しかし問題は、これらのルーチンがこのタイプの入力パラメーターを使用しているため、循環依存が発生することです。この問題をどのように解決できますか?

func_some_calc1更新: クラスのいくつかのプライベート関数を使用して非常に異なるロジックを実装するため、 と の実装をfunc_some_calc2異なるファイル (モジュラス/クラス)に保持したいことに注意してください。

module parameters_base
  type, public :: t_parameters_base
    integer :: n
  end type t_parameters_base
end module parameters_base

module parameters_problem1
  use parameters_base
  implicit none

  type, extends(t_parameters_base), public :: t_parameters_problem1
    integer :: p1
  end type t_parameters_problem1
end module parameters_problem1

module parameters_problem2
  use parameters_base
  implicit none

  type, extends(t_parameters_base), public :: t_parameters_problem2
    integer :: p2
  end type t_parameters_problem2
end module parameters_problem2

module some_calc1
  use parameters_base
  implicit none
contains
  subroutine func_some_calc1(par)
    class(t_parameters_base) :: par
  end subroutine func_some_calc1
end module some_calc1

module some_calc2
  use parameters_base
  implicit none
contains
  subroutine func_some_calc2(par)
    class(t_parameters_base) :: par
  end subroutine func_some_calc2
end module some_calc2

module some_calc3_problem1
  use parameters_problem1
  implicit none
contains
  subroutine func_some_calc3_problem1(par)
    type(t_parameters_problem1) :: par
    print*, par%p1
  end subroutine func_some_calc3_problem1
end module some_calc3_problem1

module some_calc3_problem2
  use parameters_problem2
  implicit none
contains
  subroutine func_some_calc3_problem2(par)
    type(t_parameters_problem2) :: par
    print*, par%p2
  end subroutine func_some_calc3_problem2
end module some_calc3_problem2

module main_problem1
  use parameters_problem1
  use some_calc1
  use some_calc2
  use some_calc3_problem1
  implicit none
contains
  subroutine main_func_problem1(par)
    type(t_parameters_problem1) :: par

    call func_some_calc1(par)
    call func_some_calc2(par)
    call func_some_calc3_problem1(par)
  end subroutine main_func_problem1
end module main_problem1

module main_problem2
  use parameters_problem2
  use some_calc1
  use some_calc2
  use some_calc3_problem2
  implicit none
contains
  subroutine main_func_problem2(par)
    type(t_parameters_problem2) :: par

    call func_some_calc1(par)
    call func_some_calc2(par)
    call func_some_calc3_problem2(par)
  end subroutine main_func_problem2
end module main_problem2

program module_test
  use parameters_problem1
  use parameters_problem2
  use main_problem1
  use main_problem2

  implicit none

  type(t_parameters_problem1) :: par1
  type(t_parameters_problem2) :: par2

  par1%p1 = 1
  par2%p2 = 2

  call main_func_problem1(par1)
  call main_func_problem2(par2)
end program module_test
4

1 に答える 1

0

あなたが目指しているのは、型バインドプロシージャを持つ多相型だと思います。以下に実際の例を示します。簡単にするために、型にデータを追加していませんが、もちろん簡単に行うことができます。ルーチンinvokeCalc12は基本型でのみ定義されますが、派生型から呼び出すことができます。Fortran ではすべてのメソッドが仮想であるため、適切なメソッドが呼び出されます。

module calc_base
  implicit none

  type, abstract :: CalcBase
  contains
    procedure(calcInterface), deferred :: calc1
    procedure(calcInterface), deferred :: calc2
    procedure :: invokeCalc12
  end type CalcBase

  interface
    subroutine calcInterface(self, ii)
      import :: CalcBase
      class(CalcBase), intent(inout) :: self
      integer, intent(in) :: ii
    end subroutine calcInterface
  end interface

contains

  subroutine invokeCalc12(self, ii)
    class(CalcBase), intent(inout) :: self
    integer, intent(in) :: ii
    call self%calc1(ii)
    call self%calc2(ii)
  end subroutine invokeCalc12

end module calc_base


module some_calc
  use calc_base
  implicit none

  type, extends(CalcBase) :: SomeCalc
  contains
    procedure :: calc1
    procedure :: calc2
    procedure :: calc3
  end type SomeCalc

contains

  subroutine calc1(self, ii)
    class(SomeCalc), intent(inout) :: self
    integer, intent(in) :: ii
    print *, "SomeCalc1:calc1", ii
  end subroutine calc1

  subroutine calc2(self, ii)
    class(SomeCalc), intent(inout) :: self
    integer, intent(in) :: ii
    print *, "SomeCalc1:calc2", ii
  end subroutine calc2

  subroutine calc3(self, ii)
    class(SomeCalc), intent(inout) :: self
    integer, intent(in) :: ii
    call self%%invokeCalc12(ii)
  end subroutine calc3

end module some_calc


program test
  use some_calc
  implicit none

  type(SomeCalc) :: mySimulation

  call mySimulation%calc3(42)

end program test

注: 同様の質問がcomp.lang.fortranに投稿されているのを見てきましたが、現時点では実際の例が見つからなかったため、ここに投稿します。

于 2015-06-23T14:00:47.737 に答える