在Fortran中,类型绑定过程如何链接到其派生类型? 来自C++,我知道非虚成员函数通过名称的修改与类绑定在一起。我试图学习现代Fortran,我的问题是Fortran类型绑定过程如何与它们的类型关联 例如,考虑派生类型 module shape_mod type shape integer :: color logical :: filled contains procedure :: isFilled end type shape contains logical function isFilled(this) class(shape) :: this isFilled = this%filled end function isFilled end module
我的问题是关于程序分派的内部内容。类型<代码> >代码>形状> <代码>的内存布局是否保存指向一个函数或VTABLE,当调用<代码> Sp%IsFieldSo()/Cuff>时,需要使用去引用的函数,就像C++中的虚拟成员函数所做的那样?或者类型绑定过程的名称<代码> Sp%IsFieldEnter()/Mulk >被压缩成类似于<代码>的S5ZHePuleSysSuff[S/<代码> >,如C++中的非虚拟成员函数所发生的那样? 我知道Fortran对模块中的过程使用名称混乱。这里根本不需要(额外)名称混乱。 您编写的过程完全是普通的模块过程。他们只是有一个多态的伪参数。您不必将它们称为类型绑定,您可以以正常方式使用它们 使它们成为类型绑定的是在类型声明中创建绑定在Fortran中,类型绑定过程如何链接到其派生类型? 来自C++,我知道非虚成员函数通过名称的修改与类绑定在一起。我试图学习现代Fortran,我的问题是Fortran类型绑定过程如何与它们的类型关联 例如,考虑派生类型 module shape_mod type shape integer :: color logical :: filled contains procedure :: isFilled end type shape contains logical function isFilled(this) class(shape) :: this isFilled = this%filled end function isFilled end module,fortran,name-mangling,derived-types,Fortran,Name Mangling,Derived Types,我的问题是关于程序分派的内部内容。类型 >代码>形状> 的内存布局是否保存指向一个函数或VTABLE,当调用 Sp%IsFieldSo()/Cuff>时,需要使用去引用的函数,就像C++中的虚拟成员函数所做的那样?或者类型绑定过程的名称 Sp%IsFieldEnter()/Mulk >被压缩成类似于的S5ZHePuleSysSuff[S/ >,如C++中的非虚拟成员函数所发生的那样? 我知道Fortran对模块中的过程使用名称混乱。这里根本不需要(额外)名称混乱。 您编写的过程完全是普通的模块过
procedure :: isFilled
这意味着将有一个虚拟表和一个指向虚拟表中的过程的指针,以此类推,它将为正确的实际类型指向正确的类型绑定过程
但这些程序完全是普通的。至少在概念上,我没有研究编译器,我是在描述标准概念
你可以打电话给我
type(shape) :: instance
print *, isFilled(instance)
它会工作得很好,程序本身没有什么特别之处
请注意,在扩展类型时
type, extends(shape) :: outlined_shape
integer :: outline_color
contains
procedure :: isFilled => isFilled_outlined shape
end type shape
您必须为过程使用不同的名称。因此不需要名称损坏,您已经有了一个具有不同名称的过程
logical function isFilled_outlined_shape(this)
class(outlined_shape) :: this
同样,您可以将其称为类型绑定过程:
type(outlined_shape) :: instance
print *, instance%isFilled()
但您也可以直接(非虚拟)调用它
你甚至可以直接给父母打电话
print *, isFilled(instance)
<>原因是C++使用了每个类型的虚拟函数FIR的同名名称。它没有像Fortran中那样具有不同名称的正常过程。因为如果这样,C++需要名称的修改。
考虑这个例子:
module m
type t1
contains
procedure :: s => s_t1
end type
type t2
contains
procedure :: s => s_t2
end type
contains
subroutine s_t1(self)
class(t1) :: self
end subroutine
subroutine s_t2(self)
class(t2) :: self
end subroutine
end module
在gfortran中,结果包含以下符号:
000000000000000f T __m_MOD___copy_m_T1
0000000000000000 T __m_MOD___copy_m_T2
0000000000000000 B __m_MOD___def_init_m_T1
0000000000000001 B __m_MOD___def_init_m_T2
0000000000000029 T __m_MOD_s_t1
000000000000001e T __m_MOD_s_t2
0000000000000000 R __m_MOD___vtab_m_T1
0000000000000040 R __m_MOD___vtab_m_T2
其含义如下:
0000000000000029 T __m_MOD_s_t1
000000000000001e T __m_MOD_s_t2
子例程,您可以通过这种方式直接调用它们(非虚拟)
这两种类型的内在赋值
0000000000000000 B __m_MOD___def_init_m_T1
0000000000000001 B __m_MOD___def_init_m_T2
这两种类型的默认构造函数
0000000000000000 R __m_MOD___vtab_m_T1
0000000000000040 R __m_MOD___vtab_m_T2
虚拟表函数,每种类型一个(不是每一个过程,它不是过程的名称混乱)
添加更多过程时,可以看到虚拟表如何包含指向它们的指针:
__m_MOD___vtab_m_T1:
.long 69979407
.zero 4
.quad 0
.quad 0
.quad __m_MOD___def_init_m_T1
.quad __m_MOD___copy_m_T1
.quad 0
.quad 0
.quad __m_MOD_r_t1
.quad __m_MOD_s_t1
__m_MOD___vtab_m_T2:
.long 69979408
.zero 4
.quad 0
.quad 0
.quad __m_MOD___def_init_m_T2
.quad __m_MOD___copy_m_T2
.quad 0
.quad 0
.quad __m_MOD_s_t2
.quad __m_MOD_r_t2
一个有效的问题,我希望我知道答案。如果你有gfortran,你可以看看引擎盖下它在做什么。尝试使用-fdump tree-original编译代码。NM或ObjDIP也可能有帮助。至于C++,它将依赖于编译器。你为什么想知道这个?只是好奇?思考编译器将如何实现某些东西而不是标准实际所说的东西并不总是最好的方法。我很感激你直接指向程序集(我不敢相信我没有想到它)。你说“C++需要名字的原因是因为它使用了每个类型的虚拟函数FIR的名字。”但是C++使用了非虚拟方法、命名空间、函数重载、模板特化等的名称修改。Fortran还使用了使用名称的模糊化。但我不明白为什么C++非虚方法使用名称的限制,但是FORTRAN类型绑定过程使用VTABLE间接。
0000000000000000 R __m_MOD___vtab_m_T1
0000000000000040 R __m_MOD___vtab_m_T2
__m_MOD___vtab_m_T1:
.long 69979407
.zero 4
.quad 0
.quad 0
.quad __m_MOD___def_init_m_T1
.quad __m_MOD___copy_m_T1
.quad 0
.quad 0
.quad __m_MOD_r_t1
.quad __m_MOD_s_t1
__m_MOD___vtab_m_T2:
.long 69979408
.zero 4
.quad 0
.quad 0
.quad __m_MOD___def_init_m_T2
.quad __m_MOD___copy_m_T2
.quad 0
.quad 0
.quad __m_MOD_s_t2
.quad __m_MOD_r_t2