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
然后我们可以为名为@987654322@ 的东西添加一个通用接口:
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 中的函数重载的主要内容,如果未能解决你的问题,请参考以下文章