能源与动力工程学院 目录 派生类型 陈 斌 固有数据类型 数值型 (numerical) 整型 INTEGER 实型 REAL 复数型 COMPLEX 非数值型 字符型 CHARACTER 逻辑型 ( 布尔型 )LOGICAL 自定义数据类型 ( 派生类型, derived type) 派生类型是指用户利用 Fortran 系统内部类型, 如整型 实型 复数型 逻辑型 字符型等的组合自行创建出一个新的数据类型, 它们实际上是由内部数据类型形成的某种结构 派生类型还可由其它派生类型创建而来 TYPE[, 访问属性说明 ::] 派生类型名成员 1 类型说明 成员 n 类型说明 [ 派生类型名 ] 1
TYPE STUDENT CHARACTER(20) NUNMBER LOGICAL GENDER INTEGER BIRTHDAY CHARACTER(20), DIMENSION(4) ::ADDRESS CHARACTER(10) TELEPHONE REAL, DIMENSION(20) ::MARKS TYPE(STUDENT) STUDENT1, STUDENT2 TYPE(STUDENT), DIMENSION(100) ::CLASS01 派生类型成员可以和同类型的变量一样使用, 引用派生类型成员时, 须使用成员操作符 % Student1%Birthdate = 711107 Class%Gender =.TRUE. 或者使用. Student1.Birthdate = 711107 Class.Gender =.TRUE. 同一派生类型的两个变量可以相互赋值 : Student2 = student1 派生类型的成员也可以是派生类型 TYPE point REAL :: x, y point TYPE circle TYPE (point) :: position INTEGER :: radius REAL :: area circle TYPE[, 访问属性说明 ::] 派生类型名访问属性说明 [ 派生类型名 ] 访问属性 PUBLIC( 缺省 ) PRIVATE: 该数据类型只能在模块内使用 cir%position%x = 5.0 2
MODULE MATTER TYPE, PRIVATE :: DATA... DATA END MODULE MATTER MODULE MATTER TYPE ELEMENTS integer A, B PRIVATE INTEGER C, D END MODULE MATTER 初始化 缺省初始化 在声明的同时进行初始化 显式初始化 : 利用赋值语句给派生数据类型成员赋值 利用结构构造函数在定义派生数据类型变量的同时, 给定派生数据类型各成员的值 用 DATA 语句进行显式初始化 缺省初始化 TYPE STUDENT REAL ::MARK = 60 character(20) tel 利用赋值语句 TYPE(STUDENT) ::STU1 STU1%MARK = 100 MODULE STU_TYPE TYPE STUDENT REAL ::MARK = 60 character(20) tel END MODULE 利用结构构造函数在定义派生数据类型变量的同时, 给定派生数据类型各成员的值 或者 DATA 语句赋初值 PROGRAM MAIN USE STU_TYPE TYPE(STUDENT) ::STU1 = STUDENT(" 王小二 ",49, "029-82660925") TYPE(STUDENT) ::STU2 DATA STU2/STUDENT(" 张小三 ",86, "029-82660926")/ PRINT*, STU1 PRINT*, STU2 END 3
派生数据类型不能直接使用 Fortran 自带的操作符来操作 操作符重载 需要我们自己编写程序, 重新定义已有操作符的功能或者声明新的操作符 赋值操作符重载 对已有的操作符赋予多重含义, 使同一操作符作用于不同类型的数据时产生不同的行为 其它操作符重载 赋值操作符重载 INTEFACE ASSIGNMENT( = ) interface_code 重新定义前面的 student 派生类型, 达成如下简洁操作 : 将姓名字符串直接赋给派生类型变量 Type (student_type) stu Stu = " 王小二 " 从派生类型中提取姓名, 即将派生类型变量直接赋给姓名字符变量 stuname = Stu MODULE STUDENTMODULE TYPE STUDENT_TYPE REAL MARK! 派生类型定义 program overload USE STUDENTMODULE TYPE(STUDENT_TYPE)::STUDENT = STUDENT_TYPE(" 王小二 ",50) CHARACTER(20) STUNAME INTERFACE ASSIGNMENT(=)! 赋值操作符重载必须使用接口块, 接口块须以 assignment 命名 MODULE PROCEDURE NAME_FROM_STUDENT, STUDENT_FROM_NAME SUBROUTINE NAME_FROM_STUDENT(STRING, STUDENT)! 从派生类型中提取姓名, 即将派生类型变量直接赋给姓名字符变量 CHARACTER(*), INTENT(OUT) ::STRING TYPE(STUDENT_TYPE), INTENT(IN) ::STUDENT STRING = STUDENT%NAME END SUBROUTINE SUBROUTINE STUDENT_FROM_NAME(STUDENT, STRING)! 将姓名字符串直接赋给派生类型变量 CHARACTER(*), INTENT(IN) ::STRING TYPE(STUDENT_TYPE), INTENT(OUT) ::STUDENT STUDENT%NAME = STRING END SUBROUTINE END MODULE PRINT*, STUDENT pause STUDENT = " 张小三 " PRINT*, STUDENT pause STUNAME = STUDENT PRINT*, STUNAME pause END 4
MODULE cartesian TYPE point REAL :: x, y point INTERFACE ASSIGNMENT( = ) MODULE PROCEDURE max_point SUBROUTINE max_point( a, pt ) REAL, INTENT(OUT) :: a TYPE(point), INTENT(IN) :: pt a = MAX( pt%x, pt%y ) END SUBROUTINE max_point END MODULE cartesian program assignexample USE cartesian REAL :: a a = point(1.7, 4.2) PRINT*, a END MODULE strings INTERFACE OPERATOR ( / ) MODULE PROCEDURE num INTEGER FUNCTION num( s, c ) CHARACTER(len=*), INTENT(IN) :: s CHARACTER, INTENT(IN) :: c num = 0 DO i = 1, LEN( s ) IF( s(i:i) == c ) num = num + 1 END DO END FUNCTION num END MODULE strings program string use strings print*, 'hello world' / 'l! print*, num("hello world", "z") end 可以像重载现有操作符一样定义新的操作符, 这在处理派生类型时特别有用 形式 :.name. 同样需要接口块 可以像重载现有操作符一样定义新的操作符, 这在处理派生类型时特别有用 形式 :.name. 功能 : 由 function 定义 同样需要接口块 5
MODULE cartesian TYPE point REAL :: x, y point INTERFACE OPERATOR (.DIST. ) MODULE PROCEDURE distance FUNCTION distance( a, b ) real distance TYPE(point), INTENT(IN) :: a, b distance = SQRT( (a%x-b%x)**2 + (a%y-b%y)**2 ) END FUNCTION distance END MODULE program distance use cartesian implicit none real d,e Type(point) ::p1 = POINT(1.0,1.0) Type(point) ::p2 = POINT(2.0,2.0) d = p1.dist. p2 print*, d end 6