类型绑定过程给出关于非多态传递对象虚拟参数的错误

Posted

技术标签:

【中文标题】类型绑定过程给出关于非多态传递对象虚拟参数的错误【英文标题】:Type-bound procedure gives error about non-polymorphic passed-object dummy argument 【发布时间】:2018-06-30 08:31:26 【问题描述】:

我正在尝试编译下面的 Fortran 模块(使用 gfortran 7.2.0)。关键是要定义一个派生类型,该类型又包含来自 bspline-fortran 库 (https://github.com/jacobwilliams/bspline-fortran) 的派生类型 bspline_3d 的两个实例。然后我想定义一个类型绑定过程,该过程将依次调用这两种类型的类型绑定evaluate 过程,并将结果作为包含两个元素的数组返回。

当我尝试编译下面的模块时,我收到一条错误消息

     procedure  :: evaluate => evaluate_2d
             1
Error: Non-polymorphic passed-object dummy argument of 'evaluate_2d' at (1)

我对错误消息一无所知。

我设法编译了在这里找到的简单示例程序:http://fortranwiki.org/fortran/show/Object-oriented+programming,据我所知,唯一的区别是,在我的情况下,“传递对象”(this)本身确实派生了-类型成员变量 (type(bspline_3d) :: fvx, fvy),它又可能包含各种各样的东西。

module interpolator_module

use bspline_module
use parameters, only: WP

implicit none

private
public :: interpolator

type :: interpolator
    type(bspline_3d) :: fvx, fvy
    contains
        private
        procedure  :: evaluate => evaluate_2d
end type interpolator

contains
    function evaluate_2d(this, X, t) result(V)
        implicit none
        ! inputs
        type(interpolator),     intent(inout) :: this
        real(WP), dimension(2), intent(in)    :: X
        real(WP),               intent(in)    :: t
        ! output
        real(WP), dimension(2)                :: V
        ! local variables
        integer                               :: iflag
        integer, parameter                    :: d = 0

        call this%fvx%evaluate(X(1), X(2), t, d, d, d, V(1), iflag)
        call this%fvy%evaluate(X(1), X(2), t, d, d, d, V(2), iflag)
    end function
end module interpolator_module

【问题讨论】:

【参考方案1】:

对于定义为类似的类型绑定过程

type my_type
 contains
  procedure :: proc
end type

类型绑定过程有一个传递的参数。也就是说,当

type(my_type) my_obj
call my_obj%proc

被使用,对象my_obj 在参数列表中。将proc 定义为

subroutine proc(me)
  type(my_type) me   ! Not correct
end subroutine

那么call my_obj%proc 就像call proc%(my_obj)1这是错误消息的“传递对象虚拟参数”部分。

在上面proc 的定义中,传递对象伪参数type(my_type) me 是非多态的。您可以在其他地方阅读有关多态性的信息,但要回答这个问题:传递对象的虚拟参数可能不是非多态的。它必须是多态的,使用class(my_type) me声明:

subroutine proc(me)
  class(my_type) me   ! Polymorphic, declared type my_type
end subroutine

这意味着可以传递my_type 类型或扩展my_type 类型的对象。这是 Fortran 语言的要求。

简而言之:改变你的

type(interpolator),     intent(inout) :: this

class(interpolator),     intent(inout) :: this

更复杂的是,例如,旧版本的 gfortran 在理解多态性之前理解了类型绑定过程。这意味着有一些错误使用非多态传递对象的例子。


1 我故意将绑定名称保留为proc,与过程名称相同。在问题的上下文中,它将是call my_obj%evaluate(...),例如call evaluate_2d(my_obj, ...)

【讨论】:

【参考方案2】:

传递的虚拟参数this 必须始终是多态的。这意味着它必须是

 class(interpolator),     intent(inout) :: this

而不是

 type(interpolator),     intent(inout) :: this

这是类型绑定过程的基本要求。否则你不能使用扩展类型(子)的过程。

【讨论】:

以上是关于类型绑定过程给出关于非多态传递对象虚拟参数的错误的主要内容,如果未能解决你的问题,请参考以下文章

java-多态和动态绑定

关于Qt信号与槽机制的传递方向性研究(结论其实是错误的,但是可以看看分析过程)

深入理解C++的动态绑定和静态绑定

长度参数化的传递对象到类型绑定过程有 gfortran 抱怨

回归python培训——类与对象继承多态和多态性封装绑定方法和非绑定方法反射

多态与重载