我试图了解继承如何在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也遇到了类似的错误。
这是否意味着,要覆盖父类型的过程,我们还需要处理伪参数的名称? (即,不仅使用哪个类的信息而且还有变量的名称?)
答案 0 :(得分:1)
这不是一个有良好动机的答案,但是:是的,你需要关心虚拟参数的名称。
4.5.7.3中的特定限制(在Fortran 2008中)。正如您所指出的,您在此处的内容是覆盖类型set
中类型pos
的绑定名vec
。当扩展类型中的类型绑定过程与父类型中的可访问类型绑定过程具有相同的绑定名称时,将发生重写。
如果允许改写,则在该部分给出了许多条件。值得注意的是以下两个:
如果类型绑定过程没有pass
属性,则传递对象伪参数是参数列表中的第一个参数。正如您的编译器所抱怨的那样,重写过程的传递对象名称不同。
问题的例子不使用多态,所以在某种程度上,这里不需要关心覆盖(程序可能有不同的绑定名称)。
对于需要此动态分辨率的多态工作,请确保满足上述限制。正如jlokimlin所评论的那样,对于传递的伪参数使用一个相当通用的名称,如this
或self
,它们很受欢迎,但在所有奇怪的情况下都是一种简单的方法来处理这个问题。
或者,关于覆盖的关键部分是父类的类型绑定过程是可访问的。如果两个派生类型在不同的模块中声明,并且父类型的绑定过程是私有的,则不会发生重写,并且限制不适用。 [当然,父母的绑定名称只能在其定义模块中使用,但在许多情况下这可能就足够了。]