oop - 我可以根据参数的数量重载类型绑定(bind)过程吗?

标签 oop fortran gfortran

我正在使用旧的 Fortran 编写空气动力学代码(源代码 here)。初始化的一部分是读取包含表面网格信息的文件,基本上是一组构成表面的三角形或四边形面板。我想使用单一类型的 panel 来描述四边形和三角形面板。为此,我编写了两个初始化函数 panel_init_3panel_init_4,它们将根据面板的顶点数将数据加载到类型中。我想将这些绑定(bind)到我的 panel 类型并根据参数的数量重载它们(即,如果它被传递一个整数和 3 个顶点对象,那么 panel_init_3 得到对 4 个顶点对象调用和类似。

这是该类型的源代码:

module panel_mod

    use linked_list_mod
    use vertex_mod

    implicit none


    type panel
        ! A panel with an arbitrary number of sides

        integer :: N ! Number of sides/vertices
        type(vertex_pointer),dimension(:),allocatable :: vertices
        real,dimension(3) :: n_hat ! Normal vector
        real :: A ! Surface area

        contains

            procedure :: init => panel_init_3, panel_init_4
            procedure :: calc_area => panel_calc_area
            procedure :: calc_normal => panel_calc_area

    end type panel

    
contains


    subroutine panel_init_3(this, v1, v2, v3)
        ! Initializes a 3-panel

        implicit none

        class(panel),intent(inout) :: this
        type(vertex),intent(in),target :: v1, v2, v3

        ! Set number of sides
        this%N = 3

        ! Allocate vertex array
        allocate(this%vertices(this%N))

        ! Store info
        this%vertices(1)%ptr => v1
        this%vertices(2)%ptr => v2
        this%vertices(3)%ptr => v3

        ! Calculate normal vec

        ! Calculate area

    end subroutine panel_init_3


    subroutine panel_init_4(this, v1, v2, v3, v4)
        ! Initializes a panel with 4 sides

        implicit none

        class(panel),intent(inout) :: this
        type(vertex),intent(in),target :: v1, v2, v3, v4
        
        ! Set number of sides
        this%N = 4

        ! Allocate vertex array
        allocate(this%vertices(this%N))

        ! Store info
        this%vertices(1)%ptr => v1
        this%vertices(2)%ptr => v2
        this%vertices(3)%ptr => v3
        this%vertices(4)%ptr => v4

        ! Calculate normal vector

        ! Calculate area

    end subroutine panel_init_4


    subroutine panel_calc_area(this)

        implicit none

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

    end subroutine panel_calc_area


    subroutine panel_calc_normal(this)

        implicit none

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

    end subroutine panel_calc_normal

    
end module panel_mod

这个模块编译得很好。但是,当它在这里使用时

...
! Initialize triangular panel
if (N == 3) then
   call panels(i)%init(vertices(i1+1), vertices(i2+1), vertices(i3+1)) ! Need +1 because VTK is 0-indexed

! Initialize quadrilateral panel
else
   call panels(i)%init(vertices(i1+1), vertices(i2+1), vertices(i3+1), vertices(i4+1))
end if
...

我收到编译器消息

   70 |                     call panels(i)%init(vertices(i1+1), vertices(i2+1), vertices(i3+1), vertices(i4+1))
      |                                                                                                       1
Error: More actual than formal arguments in procedure call at (1)

我是否超出了 Fortran 的能力,或者有没有办法做到这一点?我意识到我可以在没有绑定(bind)和重载的情况下完成这一切,但我喜欢它的干净程度。我正在使用 gfortran 9.3.0。

最佳答案

在类型绑定(bind)过程声明语句中,可以在一个列表中声明多个绑定(bind)名称,因此我们可以拥有

type mytype
contains
  procedure :: binding1, binding2
end type

给出两个绑定(bind)名称。这些是单独的绑定(bind)。这些绑定(bind)名称解析为具有相同名称的过程。也就是说,我们可以这样写

type mytype
contains
  procedure :: binding1 => binding1, binding2 => binding2
end type

绑定(bind)名称的列表性质是这样的

type mytype
contains
  procedure :: binding => binding1, binding2
end type

在列表 binding=>binding1binding2 中有项目。这个有效果 喜欢

type mytype
contains
  procedure :: binding => binding1, binding2 => binding2
end type

也就是说,我们仍然有两个不同的绑定(bind)名称,每个绑定(bind)名称都绑定(bind)到一个过程。

我们没有具有特定过程 binding1binding2 的通用 binding 绑定(bind)名称。为此,我们需要显式创建一个泛型:

type mytype
contains
  procedure :: binding1, binding2
  generic :: binding => binding1, binding2
end type

在此通用语句中,列表具有 binding1binding2 作为通用 binding 的具体项目。 Fortran 2018 7.5.5 中给出了这些列表/语句的精确语法规则。

关于oop - 我可以根据参数的数量重载类型绑定(bind)过程吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69138499/

相关文章:

php - OOP - 没有 GET/SET

pointers - 为什么Fortran POINTER需要一个TARGET?

Fortran 90 - 尝试读取文件末尾之后的内容

fortran - 作为派生类型组件的指针

compiler-errors - 在 cygwin/gfortran 下编译 Fortran 程序给出 "undefined reference to ` _WinMain@1 6'"

fortran - C_INCLUDE_PATH 相当于 Fortran 语言吗?

c++ - 无法从类型基类的指针访问派生类方法

Python菜鸟: Headaches with Object Oriented Programming

c# - 定义私有(private)领域和属性(property)与属性(property)

arrays - 使用 C 指针时,Fortran 数组中的更改会导致另一个数组的更改