使用相同名称覆盖父过程

时间:2016-07-24 02:02:55

标签: oop fortran

我试图了解继承如何在Fortran中工作,但是对于以下代码有困难(对不起,如果这是一个FAQ ...):

module mymod
    implicit none

    type Pos
        integer :: n_ = -1
    contains
        procedure :: set => Pos_set
    endtype

    type, extends(Pos) :: Vec
        integer :: x_ = -2
    contains
        procedure :: set => Vec_set         !! (1)
        !! procedure :: set => Vec_set_p    !! (2)
    endtype

contains

    subroutine Pos_set( p, n )
        class(Pos) p
        integer n
        p% n_ = n
    endsubroutine

    subroutine Vec_set( v, n )
        class(Vec) v
        integer n
        v% n_ = n
        v% x_ = n * 10
    endsubroutine

    subroutine Vec_set_p( p, n )
         class(Vec) p
         integer n
         p% n_ = n
         p% x_ = n * 10
    endsubroutine

end

program main
    use mymod
    implicit none
    type(Pos) p
    type(Vec) v

    call p% set( 10 )
    call v% set( 20 )

    print *, "p = ", p
    print *, "v = ", v
end

使用上面的代码,gfortran 5.2.1给出了以下错误消息:

procedure :: set => Vec_set
        1
Error: Dummy argument ‘v’ of ‘set’ at (1) should be named ‘p’
as to match the corresponding argument of the overridden procedure

如果我将set的绑定更改为Vec_set_p(即将第1行替换为2),这与Vec_set仅与第一个伪参数的名称不同,那么程序编译好并给出预期的结果。我从ifort-14.0和Oracle Fortran也遇到了类似的错误。

这是否意味着,要覆盖父类型的过程,我们还需要处理伪参数的名称? (即,不仅使用哪个类的信息而且还有变量的名称?)

1 个答案:

答案 0 :(得分:1)

这不是一个有良好动机的答案,但是:是的,你需要关心虚拟参数的名称。

4.5.7.3中的特定限制(在Fortran 2008中)。正如您所指出的,您在此处的内容是覆盖类型set中类型pos的绑定名vec。当扩展类型中的类型绑定过程与父类型中的可访问类型绑定过程具有相同的绑定名称时,将发生重写。

如果允许改写,则在该部分给出了许多条件。值得注意的是以下两个:

  • 传递对象伪参数(如果有)应与名称和位置相对应。
  • 按位置对应的虚拟参数应具有相同的名称和特征,但传递对象伪参数的类型除外。

如果类型绑定过程没有pass属性,则传递对象伪参数是参数列表中的第一个参数。正如您的编译器所抱怨的那样,重写过程的传递对象名称不同。

问题的例子不使用多态,所以在某种程度上,这里不需要关心覆盖(程序可能有不同的绑定名称)。

对于需要此动态分辨率的多态工作,请确保满足上述限制。正如jlokimlin所评论的那样,对于传递的伪参数使用一个相当通用的名称,如thisself,它们很受欢迎,但在所有奇怪的情况下都是一种简单的方法来处理这个问题。

或者,关于覆盖的关键部分是父类的类型绑定过程是可访问的。如果两个派生类型在不同的模块中声明,并且父类型的绑定过程是私有的,则不会发生重写,并且限制不适用。 [当然,父母的绑定名称只能在其定义模块中使用,但在许多情况下这可能就足够了。]