数据类型与过程绑定:深入解析及应用
立即解锁
发布时间: 2025-08-16 01:29:53 阅读量: 12 订阅数: 38 


Fortran 2003: 完整语法与特性指南
# 数据类型与过程绑定:深入解析及应用
## 1. 存储序列
对于序列类型,不同类型的存储序列有不同要求:
- 对于数值和字符序列类型,其对象的组件必须按指定顺序存储,且无填充。
- 对于其他序列类型,虽然标准规定了组件的存储单元序列,但标准程序无法检测,编译器可重新排列内部存储,只要保证类型等价规则仍适用。
- 对于非序列类型,标准未暗示内部存储顺序。
## 2. 过程类型绑定
过程类型绑定将派生类型与过程连接起来,有绑定的过程常被称为类型绑定过程。类型绑定在派生类型定义的类型绑定部分指定,形式如下:
```fortran
CONTAINS
[ PRIVATE ]
procedure-binding-statement
[ procedure-binding-statement ] ...
```
其中,`PRIVATE` 语句可选,且类型绑定部分至少需要一个过程绑定语句。过程绑定语句有以下三种形式:
- 特定绑定(Specific Bindings)
- 通用绑定(Generic Bindings)
- 最终绑定(Final Bindings)
### 2.1 特定绑定
特定绑定分为延迟绑定和非延迟绑定:
- 非延迟特定绑定形式:
```fortran
PROCEDURE [ [ , NON_OVERRIDABLE ] [ , binding-attribute-list ] :: ] &
binding-name [ => procedure-name ]
```
- 延迟特定绑定形式:
```fortran
PROCEDURE ( interface-name ) , DEFERRED [ , binding-attribute-list ] :: binding-name
```
绑定属性包括:
- `PASS [ ( argument-name ) ]`
- `NOPASS`
- `access-spec`
规则和限制如下:
1. 同一绑定属性在给定绑定属性列表中不得指定多次。
2. 若非延迟特定绑定中省略过程名,则默认与绑定名相同。
3. 若非延迟特定绑定中显式出现过程名,则必须使用双冒号分隔符。
4. 非延迟特定绑定中的过程名必须是可访问的模块过程或具有显式接口的外部过程的名称。
特定过程类型绑定在语法和功能上与过程指针组件有相似之处,但也有区别。对于过程指针组件,类型的每个对象都有一个单独的指针,可指向不同的过程;而对于特定绑定,同一类型的所有对象使用相同的过程。
示例代码如下:
```fortran
module procedure_binding_example
type t
real :: a
contains
procedure, pass(arg) :: print_me
procedure, pass(arg) :: print_my_square
end type t
contains
subroutine print_me (arg, lun)
type(t), intent(in) :: arg
integer, intent(in) :: lun
write (lun,*) arg%a
end subroutine print_me
subroutine print_my_square (arg, lun)
type(t), intent(in) :: arg
integer, intent(in) :: lun
write (lun,*) arg%a**2
end subroutine print_my_square
end module procedure_binding_example
program main
use procedure_binding_example
use iso_fortran_env, only :: output_unit
type(t) :: x
x%a = 2.71828
call x%print_me(output_unit)
call x%print_my_square(output_unit)
end program main
```
这个示例展示了特定绑定的使用,以及与普通过程调用的区别。
### 2.2 通用绑定
通用绑定的形式为:
```fortran
GENERIC [ , access-spec ] :: generic-spec => binding-name-list
```
规则和限制如下:
1. 每个绑定名必须是该类型特定绑定的名称。
2. 若通用规范是针对运算符、赋值或派生类型输入/输出,则每个绑定必须有一个传递对象的虚拟参数,且绑定的接口必须符合相应规范。
3. 同一派生类型定义中,具有相同通用规范的所有通用绑定必须具有相同的可访问性。
4. 特定通用规范的特定绑定集必须满足通用解析的要求,包括任何继承的相同通用规范的绑定。
示例:
```fortran
procedure :: invert_single
procedure :: invert_double
procedure :: invert_huge_single
procedure :: invert_huge_double
generic :: operator(.invert.) => invert_single, invert_double, &
& invert_huge_single, invert_huge_double
```
### 2.3 最终绑定
最终绑定形式为:
```fortran
FINAL [ :: ] final-subroutine-name-list
```
规则和限制如下:
1. 每个最终子例程名必须是具有一个虚拟参数的模块过程的名称,该虚拟参数必须是正在定义的类型,且不能是可选、指针、可分配、多态或 `INTENT (OUT)` 的,其长度类型参数必须是假定的。
2. 同一类型的任意两个最终子例程的虚拟参数的秩或种类类型参数必须不同,且同一最终子例程不得指定两次。
最终绑定类似于其他语言中的析构函数。类型可终结化的条件是具有最终子例程或具有可终结化类型的非指针、非可分配组件。数据实体可终结化的条件是属于可终结化类型且不是指针。
最终化过程包括以下三个步骤:
1. 调用数据实体的最终子例程,将数据实体作为实际参数。
2. 对类型定义中指定的每个可终结化组件进行最终化。
3. 若数据实体是扩展类型且父类型可终结化,则对父组件进行最终化。
最终化发生的情况如下:
1. 指针释放时,其目标被最终化;可分配实体释放时,自身被最终化。
2. 过程执行完成导致实体未定义时,实体被最终化。
3. 可执行构造中引用的函数结果或结构构造函数在包含该引用的最内层可执行构造执行后被最终化。
4. 规范表达式中引用的函数结果或结构构造函数在作用域单元的第一个可执行语句执行前被最终化。
5. 调用过程时,与 `INTENT (OUT)` 虚拟参数关联的非指针、非可分配实际参数被最终化。
6. 执行内在赋值语句时,变量在定义前、表达式求值后被最终化。
7. 通过指针分配的目标变得不可达时,可在后续任何时间由处理器选择进行最终化。
示例代码:
```fortran
module linked_list_module
type linked_list_node_type
real, allocatable :: data(:)
type(linked_list_node_type), pointer :: next
contains
final :: finalize_node
end type
contains
recursive subroutine finalize_node (node)
type(linked_list_node_type) :: node
if (associated(node%next)) deallocate(node%next)
end subroutine
. . .
end module
```
## 3. 类型扩展与继承
类型扩展是基于先前定义的类型定义新类型的方法,新类型可添加类型参数、组件和过程绑定,也可覆盖过程绑定。
### 3.1 类型扩展基础
任何既不是序列也不是绑定类型的派生类型都是可扩展的。使用 `EXTENDS` 类型属性的类型定义定义扩展类型,父类型必须是可扩展类型。扩展类型也是可扩展的,可形成树状结构。
扩展类型继承父类型的所有类型参数和组件,以及未被覆盖的特定和通用绑定。扩展类型还有一个特殊的隐式声明组件——父组件,用
0
0
复制全文
相关推荐









