参考:彭国伦:《Fortran 95程序设计》,2002年,第11章
目录
1. 重载(overload)
概念:函数名称相同,但参数类型、数目不同的函数。程序会自动根据输入的参数,来决定要调用哪一个函数。
实现:使用interface来定义一个虚拟函数(即所谓相同的函数名),并给出虚拟函数的实现方式(即参数类型、数目不同的函数具体实现)。
示例:
module mod_show
implicit none
! 函数的重载
interface show
module procedure show_int
module procedure show_character
end interface
contains
subroutine show_int(n)
implicit none
integer :: n
write(*,*) n
end subroutine show_int
subroutine show_character(string)
implicit none
character(len=*) :: string
write(*,*) TRIM(string)
end subroutine show_character
end module
program case_overload
use mod_show
implicit none
call show(333)
call show("666")
stop
end program
结合示例分析,虚拟函数即show。其有两个版本,一个是输入参数类型为integer,另一个为characater(len=*)。其实现时所使用的函数名并无要求,只要能对应interface中的即可。
注意,Fortran并没有将重载函数的具体实现封装起来。也就是说不允许通过private来限制具体实现的函数。在use这个module的地方,也可直接调用具体实现的函数(此处即为show_int(), show_character())。
2. 自定义操作符
自定义操作符的实现与函数的重载类似,需通过interface来完成。这里自定义操作符的应用场景多正对自定义类型(TYPE)。
示例:
module time_util
implicit none
! 自定义时间的数据结构
type :: time
integer :: hour, minute
end type time
! 适用于自定义数据结构的+的interface
interface operator(+)
module procedure add_time
end interface
contains
function add_time(a, b)
implicit none
! variables
type(time), intent(in) :: a, b
!type(time) :: a, b
type(time) :: add_time
! function body
add_time%hour = a%hour + b%hour
add_time%minute = a%minute + b%minute
add_time%hour = add_time%hour + add_time%minute/60
add_time%minute = mod(add_time%minute, 60)
return
end function add_time
subroutine show_time(a)
implicit none
type(time), intent(in) :: a
write(*, "(I2, ':', I2)") a%hour, a%minute
end subroutine
end module
program Chapter11
use time_util
implicit none
! Variables
character(len=20) :: dates, times
type(time) :: time_mon, time_tue, time_total
time_mon = time(1, 45)
time_tue = time(2, 18)
time_total = time_mon + time_tue
call show_time(time_total)
stop
end program
自定义操作符同函数重载的区别在于interface后跟着operator (+),此处以+为例。
注意:
具体实现的函数,必须明确每一个参数属性的intent。
此处大多使用的是function,而非subroutine。Fortran中一个不成文的规定:传递给function的参数,只要读取它的数值就好了,不要去改变它的数据。这也意味着通常为intent(in)
上述只实现了自定义类型(time)的相加,也可进一步实现time同real的相加。
代码如下:
module time_util
implicit none
! 自定义时间的数据结构
type :: time
integer :: hour, minute
end type time
! 适用于自定义数据结构的+的interface
interface operator(+)
module procedure add_time
module procedure add_real
end interface
contains
function add_time(a, b)
implicit none
! variables
type(time), intent(in) :: a, b
!type(time) :: a, b
type(time) :: add_time
! function body
add_time%hour = a%hour + b%hour
add_time%minute = a%minute + b%minute
add_time%hour = add_time%hour + add_time%minute/60
add_time%minute = mod(add_time%minute, 60)
return
end function add_time
function add_real(a, num_real)
implicit none
! variables
type(time), intent(in) :: a
real, intent(in) :: num_real ! integer可强制转换成real???
type(time) :: b ! local variable
type(time) :: add_real
! function body
! 即使function real2time写在后面也是可以的
b = real2time(num_real)
add_real%hour = a%hour + b%hour
add_real%minute = a%minute + b%minute
add_real%hour = add_real%hour + add_real%minute/60
add_real%minute = mod(add_real%minute, 60)
return
end function add_real
! 将real转换为time
function real2time(num_real)
implicit none
! variables
real, intent(in) :: num_real
type(time) :: real2time
! function body
! 通过int()将浮点型显式地强制转换,是否存在四舍五入
! real2time%hour = int(num_real)
! time中hour为integer,隐式地转换
! real2time%hour = num_real
real2time%hour = num_real/1
! 小数转换为分钟
! 若存在小数应当四舍五入,暂略
! ... ...
real2time%minute = mod(num_real, 1.0)*60
return
end function
subroutine show_time(a)
implicit none
type(time), intent(in) :: a
write(*, "(I2, ':', I2)") a%hour, a%minute
end subroutine
end module
program Chapter11
use time_util
implicit none
! Variables
character(len=20) :: dates, times
type(time) :: time_mon, time_tue, time_total
time_mon = time(1, 45)
time_tue = time(2, 18)
time_total = time_mon + time_tue
call show_time(time_total)
time_total = time_tue + 1.5
call show_time(time_total)
stop
end program
输出结果为:
4: 3
3:48
此外,还可以实现同一个interface中多种操纵符号的定义。
语法如下:
interface operator(+) or (-) or (*)
module procedure add_time
module procedure minus_time
module procedure multi_time
end interface
不多此时要实现多种加法怎么办呢?
3. 继承Module
Fortran中的继承也很简单,粗略的说就是在mod_b中use mod_a,mod_b即继承了mod_a所有public的变量和函数。
在练习过程中产生的疑惑:
在mod_b中use mod_a,在program中use mod_b,能否在program中使用mod_a中公开的变量或函数呢?
答案:可以的!(?大多数可实现继承的编程语言都这样设计的?)
示例:
module mod_a
implicit none
integer :: ma = 10
contains
subroutine mod_a_SoberHi()
write(*,*) "Sober Hi From mod_a"
end subroutine mod_a_SoberHi
end module mod_a
module mod_b
use mod_a
implicit none
integer :: mb = 20
contains
subroutine mod_b_SoberHi()
write(*,*) "Sober Hi From mod_b"
end subroutine mod_b_SoberHi
end module mod_b
program case_inherit
use mod_b
call mod_a_SoberHi()
call mod_b_SoberHi()
write(*, *) ma
write(*, *) mb
stop
end program case_inherit
输出结果:
Sober Hi From mod_a
Sober Hi From mod_b
10
20
这篇笔记介绍了Fortran中的函数重载,通过interface定义虚拟函数,实现不同参数类型的调用。自定义操作符用于自定义类型的操作,如自定义时间类型的时间加法。此外,还探讨了Module的继承机制,如何在子Module中使用父Module的public成员。
3913

被折叠的 条评论
为什么被折叠?



