Fortran 2008 中的函数重载

Posted

技术标签:

【中文标题】Fortran 2008 中的函数重载【英文标题】:Function overloading in Fortran 2008 【发布时间】:2018-11-07 22:19:20 【问题描述】:

我从 Fortran 2008 开始,我在 OOP 方面遇到了很大的困难。看来,在 2008 年语言标准中解释一个非常基本的 OOP 概念的资料很少。

我找到了关于继承的信息,但是我找不到任何关于多态性的信息。

所以如果我想在 C++ 中重载一个函数,我可以这样做(来自 Wikipedia 的示例):

// volume of a cube
int volume(const int s)

    return s*s*s;


// volume of a cylinder
double volume(const double r, const int h)

    return 3.1415926*r*r*static_cast<double>(h);


// volume of a cuboid
long volume(const long l, const int b, const int h)

    return l*b*h;

但是,我应该如何在 Fortran 2008 中做同样的事情?

【问题讨论】:

我现在没有时间回答这个问题,但是如果您访问 Portland Group 网站并在周围搜索一下,您会发现几年前写的一些文章可能是最好的介绍材料免费提供的 Fortran OOP 主题。 您的示例并不是真正的“OOP”,但 generics 的概念(从 Fortran 90 开始)将是合适的。这里可能有一组很好的问题来解决它们的基本用途,但你肯定会发现很多问题都将它们放在心上。 此外,您提到了“多态性”,但在您的示例中与(Fortran 的)多态性没有任何关系。您是在询问如何在 Fortran 中执行与 C++ 示例相同的操作,还是询问如何解决存在多态性的过程? [这是两件相关的事情,但又足够不同,以至于作为一个问题涵盖两者可能过于广泛。] @francescalus 好的,很抱歉让您感到困惑。我在问,我怎样才能重载函数以具有相同的标识符,但不同的参数。我提到了 OOP,因为我打算将它主要用于方法重载。 以下是@HighPerformanceMark 提到的链接:Code Reusability、Data Polymorphism(可能与您的特定问题最相关)、Parameterized Derived Types 和 User-Defined Derived Type Input/Output 【参考方案1】:

C++ 示例中给出的重载思想在 Fortran 中得到了实现,可以追溯到 Fortran 90 的泛型

给定一组特定过程,可以使用通用标识符来标识该组。在这个答案中,我将对这个概念进行非常高级的介绍。有很多微妙之处可能需要进一步阅读/解决问题。

与 C++ 示例不同,我们的 Fortran 特定过程需要单独命名。让我们有两个功能(第三个可以添加比照

integer function volume_cube(s)
  integer, intent(in) :: s
  ...
end function volume_cube

double precision function volume_cylinder(r, h)
  double precision, intent(in) :: r
  integer, intent(in) :: h
  ...
end function volume_cylinder

然后我们可以为名为@9​​87654322@ 的东西添加一个通用接口:

interface volume
  procedure volume_cube, volume_cylinder
end interface

然后我们可以引用泛型volume,编译器将确定使用哪个特定函数。

还有很多关于泛型的知识,包括除了这个简单的重载之外它们还提供什么。人们还应该了解如何解决特定程序(在这种情况下很简单,在其他情况下则不然)以及对哪些特定程序可能混为一谈的限制。当您使用泛型时,有问题的案例可能会有特定的问题。我在这里回答只是因为我看不到一个介绍性的问题,而且我没有试图解决许多不同的困难或价值观。


完整示例

module mod

  private

  interface volume
     module procedure volume_cube, volume_cylinder
  end interface volume
  public volume

contains
  integer function volume_cube(s)
    integer, intent(in) :: s
    volume_cube = s**3
  end function volume_cube

  double precision function volume_cylinder(r, h)
    double precision, intent(in) :: r
    integer, intent(in) :: h
    volume_cylinder = 3.1415926d0*r**2*h
  end function volume_cylinder

end module mod

  use mod

  print*, volume(2), volume(2d0,4)
end

【讨论】:

非常感谢!您介意在课堂上提及这些泛型的可能用法吗?我的意思是具体的方法重载。 “在课堂上”是什么意思?我认为您的意思是(您可以查找术语以检查)通用类型绑定过程。不幸的是,在这些情况下,一些重大并发症开始发挥作用。如果你是这个意思,我建议先阅读类型绑定程序,然后在必要时提出一个新的具体问题。 (我不认为我可以在包含这些内容时保持这个答案简洁 - 但这些内容很有趣。)【参考方案2】:

扩展 Fancescalus 示例:

module Pablo_Dali
private

interface volume_Cube
  module procedure volume_cube_Int, volume_cube_Float, Colume_cube_Double
!add in 8, 16, and 64 bit ints... and complex??
end interface volume
public volume_Cube

contains
  integer function volume_cube_Int(s)
    integer, intent(in) :: s
    volume_cube_Int = s**3
  end function volume_cube_int

  float function volume_cube_Float(s)
    float, intent(in) :: s
    volume_cube_float = s**3
  end function volume_cube_Float

  integer function volume_cube_Double(s)
    DOUBLE, intent(in) :: s
    volume_cube_Double = s**3
  end function volume_cube_Double
end module Pablo_Dali

然后是代码:

PROGRAM Cube_Volume
USE Pablo_Dali
IMPLICIT NONE

INTEGER :: I_Side, I_Volume
FLOAT   :: F_Side, F_Volume
DOUBLE  :: D_Side, D_Volume

I_Side = 1
F_Side = 1.0E0
D_Side = 1.0D0

WRITE(*,*)'[INT]    ',I_Side,' cubed=', volume_cube(I_Side)
WRITE(*,*)'[FLOAT]  ',F_Side,' cubed=', volume_cube(F_Side)
WRITE(*,*)'[DOUBLE] ',D_Side,' cubed=', volume_cube(D_Side)

END PROGRAM Cube_Volume

【讨论】:

以上是关于Fortran 2008 中的函数重载的主要内容,如果未能解决你的问题,请参考以下文章

类中的函数重载

类中的函数重载

错误:没有重载函数的实例

类中的函数重载(二十三)

C++深度剖析学习总结 22 类中的函数重载

C++深度剖析学习总结 22 类中的函数重载