Fortran 2003/2008中类(*)的过程继承规则
考虑以下代码Fortran 2003/2008中类(*)的过程继承规则,fortran,Fortran,考虑以下代码 module classes Type AData end Type Type A contains procedure :: Work end type Type, extends(AData) :: BData end Type Type, extends(A) :: B contains procedure :: Work => Work2 end type contains subroutine Work(this, D) class(A) :: this
module classes
Type AData
end Type
Type A
contains
procedure :: Work
end type
Type, extends(AData) :: BData
end Type
Type, extends(A) :: B
contains
procedure :: Work => Work2
end type
contains
subroutine Work(this, D)
class(A) :: this
class(*) :: D
end subroutine
subroutine Work2(this, D)
class(B) :: this
class(BData) :: D
end subroutine
end module classes
这有效吗?ifort接受它,gfortran拒绝它(因为Work2的第二个参数中的类不相同)
如果它无效,在某些情况下似乎很有用:如果有更多不同类型的参数,子过程必须有多个嵌套的“select type”语句才能将参数转换为预期类型。如果在编译时知道子类中的参数将具有什么类型,那么这将非常冗长,而且效率可能也会降低(代价是丢失一些编译时一致性检查)。是否有编译器选项使gfortran接受此构造,还是应该是gcc错误报告/功能请求
--编辑--:
明确地说,Gfortran 4.9提供了
错误:在(1)处重写过程“work”的参数不匹配:参数“d”(类(bdata)/CLASS(*)中的类型不匹配
ifort(但不是gfortran)也允许构造,例如
subroutine Work2(this, D)
class(B) :: this
class(*), target :: D
class(BData), pointer :: B
B=>D
end subroutine
因此,似乎将类(星型)变量视为具有开发人员提供的“相信我,我知道它是什么类型”标记。在我看来,这似乎非常合理(如果使用较少),并避免了选择类型操作中的开销,有时避免了非常冗长的多个嵌套选择类型语句。我所知道的进行盲类型转换的唯一其他有效方法是通过一个外部子例程推送东西,在这个子例程中根本没有对参数进行类型检查(在f90中绕过传递aribitrary类型参数的可怕方法)
使用其他类型重写类(星型)过程的愿望也出现在一些基本上下文中,比如最小化库,您希望在其中传递函数和任意对象。在这里,开发人员和特定函数实现始终知道对象的类型,即使最小值不知道,因此您不希望在函数实现中使用class(*)参数执行“选择类型”。在
B
中的类型绑定过程覆盖a
中的类型绑定过程,n Fortran 2008标准第4.5.7.3节
超控和超控类型绑定程序应满足以下条件
- 按位置对应的伪参数应具有相同的名称和特征,但传递的对象伪参数的类型除外
D
在两个子例程中必须是相同的类型。因此,最小的变化实际上是在至少work2
中有一个select-type
构造(可能有class(Adata)
作为两个子例程中的声明)
然而,以下方法是否可行
module classes
Type AData
end Type AData
Type A
contains
procedure :: work_adata
generic :: Work => work_adata
end type A
Type, extends(AData) :: BData
end Type BData
Type, extends(A) :: B
contains
procedure :: work_bdata
generic :: work => work_bdata
end type B
contains
subroutine Work_adata(this, D)
class(A) :: this
type(Adata) :: D
end subroutine Work_adata
subroutine Work_bdata(this, D)
class(B) :: this
type(BData) :: D
end subroutine Work_bdata
end module classes
这可以通过为假人使用类型声明来解决数据类多态性带来的困难。谢谢。泛型方法在这样的典型应用中是否有效:子例程测试(X,D)类(A)::X类(AData)::D调用X%工作(D)结束子例程-我认为很不幸不是这样?是的,如果你想充分利用多态性,那么
选择类型s必须出现在某个地方,在测试
或工作
中。通用方法只是另一个选项(您可以通过使test
本身通用来扩展它)。哪一种更好取决于您的总体设计以及各种类型之间的关联程度。为了证实这一点,Intel还表示ifort接受的两种形式都是编译器错误,并提出了一些问题供将来修复。在代码中使用gfortran 4.8.2时,我被告知“错误:覆盖过程“工作”的参数不匹配(1):参数“d”中的类型/秩不匹配“这就是您所指的问题吗?编辑问题以添加更多信息您关于允许的指针赋值形式的其他信息与最初关于过程特征匹配要求的问题并不相关。class()并不是您真正想要的“信任我”。TS29113是增强C互操作性的技术规范,它增加了TYPE()和DIMENSION(..)以等效于C的void*。虽然主要用于从Fortran调用C,但您可以用这种方式声明带有参数的Fortran例程,但它通常需要将伪对象“强制转换”为已知类型。这是目前所谓的Fortran 2015规范的一部分。