1

我正在使用 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”永远是同一个类型。有没有办法减少嵌套的select类型?(如果我有很多中间变量,那将是一场灾难。)

4

1 回答 1

2

您的示例代码中没有函数。

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

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

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

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

但是通常没有什么可以阻止您为您的过程编写一个与 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 等延迟抽象父类型的绑定,并具有实际存储数据的扩展(不使用无限多态变量)然后提供操作的实现作为这些延迟绑定的覆盖。这更接近您上一个问题中的第一种方法。

于 2014-09-26T03:02:04.510 回答