Fortran 2008 中的函数重载
Function overloading in Fortran 2008
我刚开始使用 Fortran 2008,但在 OOP 方面遇到了很大困难。看来,2008语言标准中解释一个非常基本的OOP概念的资料很少。
我找到了有关继承的信息,但找不到有关多态性的任何信息。
所以如果我想在 C++ 中重载一个函数,我可以这样做(示例来自维基百科):
// 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 中做同样的事情?
C++ 示例中给出的重载思想在 Fortran 中有一个实现,可以追溯到 Fortran 90 的泛型。
给定一组特定 过程,可以使用通用标识符来标识该组。在这个答案中,我将对这个概念进行非常高层次的介绍。有很多细微之处可能需要进一步 reading/questions 来解决。
与 C++ 示例不同,我们的 Fortran 特定过程需要单独命名。让我们有两个功能(第三个可以添加mutatis mutandis)
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
然后我们可以为名为 volume
:
的东西添加一个通用接口
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
扩展 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,但在 OOP 方面遇到了很大困难。看来,2008语言标准中解释一个非常基本的OOP概念的资料很少。
我找到了有关继承的信息,但找不到有关多态性的任何信息。
所以如果我想在 C++ 中重载一个函数,我可以这样做(示例来自维基百科):
// 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 中做同样的事情?
C++ 示例中给出的重载思想在 Fortran 中有一个实现,可以追溯到 Fortran 90 的泛型。
给定一组特定 过程,可以使用通用标识符来标识该组。在这个答案中,我将对这个概念进行非常高层次的介绍。有很多细微之处可能需要进一步 reading/questions 来解决。
与 C++ 示例不同,我们的 Fortran 特定过程需要单独命名。让我们有两个功能(第三个可以添加mutatis mutandis)
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
然后我们可以为名为 volume
:
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
扩展 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