过程绑定

Fortran2003开始支持过程绑定,将子程序或者函数与对应的类型相关联,使用的方法和访问成员类似。这样的做法可以提高代码的一致性。

过程绑定的语法

过程绑定中, 对应子过程的虚参声明需要使用class关键字。同时在类型的定义中使用procedure关键字将其绑定,使用contains将类型和函数分开。

析构函数

程序运行结束之后,这个对象需要释放,此时使用final关键字可以指定一个函数为析构函数。当释放的时候就会调用这个函数。

module vector_mod
  implicit none
  type vector_t
    real,allocatable::x(:)
    integer::capacity
    integer::size
  contains
    procedure,pass:: init => vector_init
    procedure,pass:: append => vector_append
    final :: vector_final
  end type vector_t
contains
  subroutine vector_init(this,n)
    class(vector_t),intent(inout)::this
    integer,intent(in)::n
    allocate(this%x(n))
    this%size=0
    this%capacity=n
  end subroutine vector_init

  subroutine vector_append(this,val)
    class(vector_t),intent(inout)::this
    real,intent(in)::val
    this%size=this%size+1
    this%x(this%size)=val
  end subroutine vector_append

  subroutine vector_final(this)
    type(vector_t),intent(inout):: this !此处是type 不是class
    if(allocated(this%x))deallocate(this%x) !释放可分配数组
    this%size=0
    this%capacity=0
    write(*,*)"call final" 
  end subroutine vector_final
end module vector_mod

program main
  use vector_mod
  implicit none
  block
    type(vector_t)::v
    call v%init(10)
    call v%append(1.0)
    call v%append(2.0)
    write(*,*)v%x(1:v%size)
  end block !离开作用域时会调用析构函数
  write(*,*)"done"
end program main
  • pass关键字用来指定在调用的过程中,被调用的类型会自动传递为第一个虚参,与之对应的还有nopass,不自动传递
  • pass(this)关键字也可以带具体的参数,用于指定哪个虚参被自动传递。当你的函数中有多个虚参都是当前类型的时候,你可以指定任意一个。
  • 使用=>可以为绑定的过程重命名。
  • 被绑定的变量名尽量使用this或者self(与其他语言的习惯相符)

习题

  • vector的append 函数并没有考虑超过capacity的情况。重写这个函数,使其可以在元素超出的时候自动扩容。
  • (附加题)使用move_alloc子程序完成上述功能。
  • 使用我们之前提到的函数重载功能重载size函数,使得size(v)返回v%size
  • 使用size(v)返回v%size会带来什么问题,提示(定义vector_t类型的数组)