FORTRAN:传递无限多态子程序作为参数和其他问题

时间:2014-09-26 01:52:44

标签: arguments fortran subroutine polymorphism fortran2003

我使用FORTRAN oop功能进行编程。现在我有一个子程序,它将另一个子程序作为其参数。但我希望子程序采用无限多态子程序作为参数以及普通子程序。例如,我有:

    subroutine PassFunc(MyFunc, MyInput)
        class(*), intent(inout) :: MyInput
        interface
            subroutine MyFunc(A, B)
                class(*), intent(in) :: A
                class(*), intent(out) :: B
            endsubroutine MyFunc
        endinterface
        class(*), allocatable :: FuncRes

        select type(MyInput)
        type is(real(8))
            allocate(real(8)::FuncRes)
            select type(FuncRes)
            type is(real(8))
                call MyFunc(MyInput, FuncRes)
                MyInput = MyInput + FuncRes**2
            endselect
        type is(complex(8))
        endselect
    endsubroutine PassFunc

    !Input Functions
    subroutine Func1(A, B)
        class(*), intent(in) :: A
        class(*), intent(out) :: B

        select type(A)
        type is(real(8))
            select type(B)
            type is(real(8))
                B = A + 1
            endselect
        type is(complex(8))
            select type(B)
            type is(complex(8))
                B = A - 1
            endselect
        endselect
    endsubroutine Func1

    subroutine Func2(A, B)
        real(8), intent(in) :: A
        real(8), intent(out) :: B

        B =  A + 1
    endsubroutine Func2

问题:

  1. 我只允许将无限多态子程序传递给“PassFunc”。我无法传递正常函数(没有类(*)的函数)。有没有办法让“PassFunc”采用其他类型的功能? (例如:Func1有效,但Func2没有。我有IVF的访问冲突,虽然它在编译时没有抱怨。是否可以使它工作?如果有可能,我可以使用其他子程序而无需修改。 )

  2. 在这种情况下,“FuncRes”变量的类型取决于“MyInput”。现在我知道的唯一方法是使用嵌套的选择类型。但事实上,没有必要这样做,因为“FuncRes”和“MyInput将始终是相同的类型。有没有办法减少嵌套的选择类型?(如果我有许多中间变量,这将是一场灾难。)

1 个答案:

答案 0 :(得分:1)

示例代码中没有函数。

具有多态参数的过程在引用过程时或者当此类过程是目标时,需要为过程显式接口是指针赋值语句。引用需要显式接口的过程的指针也必须具有显式接口。这实际上意味着,如果您想要使用显式接口,那么总是必须有一个显式接口,用于需要显式接口的过程。

如果涉及显式接口,则与伪参数关联的过程的特征必须匹配。声明的参数类型是过程的特征,因此参数必须在声明的类型中匹配。匹配在这里意味着“相同”,在某种程度上兼容是不够的。

当显式接口可用时,编译器应该能够检查接口是否匹配。虽然他们不需要检查 - 未能检测到不匹配可能会被视为编译器错误。

因此,如果涉及多态参数,则无法采用其他类型的过程。

但是通常没有什么能阻止你为你的程序编写一个与PassFunc想要的接口相匹配的包装器(所以你把它传递给PassFunc)并且可以为你调用Func2。

SUBROUTINE Func2_wrapper(A,B)
  CLASS(*), INTENT(IN) :: A
  CLASS(*), INTENT(OUT) :: B
  SELECT TYPE (A)
  TYPE IS (REAL)
    SELECT TYPE (B)
    TYPE IS (REAL)
      CALL Func2(A,B)
    END SELECT
  END SELECT
END SUBROUTINE Func2_wrapper

对于你的第二个问题,没有一般方法可以避免使用你选择的实现方法进行嵌套 - 如果你希望Func1处理在其参数中抛出的任何类型(更糟糕的情况是任何类型的组合)。

但是,替代设计可能会让您逃脱单一级别。这在某种程度上取决于你要做什么......但更合适的方法可能是使操作Func1,Func2等延迟绑定抽象父类型,实际存储数据的扩展(不使用无限多态变量)然后提供操作的实现作为那些延迟绑定的覆盖。这更接近您上一个问题中的第一种方法。