当前位置:文档之家› 第六章_派生类型

第六章_派生类型


SUBROUTINE Print_student(this) TYPE(Student),INTENT(in)::this PRINT*,this END SUBROUTINE END MODILE PROGRAM Main USE Stu_Type IMPLICIT NONE TYPE(Student)::stu CALL Student_(stu,”Smith,JR”) CALL Print_Student(stu) END PROGRAM
INTERFACE OPERATOR(*) !接口块以 OPERATOR 命名,重载操作符 命名, 接口块以 MODULE PROCEDURE Intersect END INTERFACE CONTAINS FUNCTION BuildSet(V) !函数返回值为派生类型 函数返回值为派生类型 TYPE(SET)BuildSet INTEGER V(:) !延迟形状数组参数 延迟形状数组参数 INTEGER J BuildSet%Cardinality = 0 DO J = 1, SIZE(V) IF(.NOT.(V(J).IN.BuildSet))THEN IF(BuildSet%Cardinality<MaxCard)THEN BuildSet%Cardinality = BuildSet%Cardinality+1 BuildSet%Members(BuildSet%Cardinality) = V(J) ELSE PRINT*,’Maximum set size exceeded-adjust MaxCard’ STOP END IF END IF END DO END FUNCTION BuildSet
程序说明:
(1)由于将派生类型的成员声明为私有的,不能在模块外部对其初始化。在程 序中设计了一个类似于 C++ 构造函数的公有例程,以便对其初始化; (2)使用了可选参数设计构造例程,在初始化时可以灵活决定是否传入可选参 数,例如: CALL Student_(stu,“Smith,JR”) !省略可选参数 CALL Student_(stu,“Smith,JR”,70.0) !传入可选参数 (3)如果派生类型的成员是公有的,可以通过派生类型变量名直接输出其成员 (见例6-1);如果派生类型的成员是私有的,需要设计专门的输出例程(见 例6-2)
针对上述创建的学生数据类型,
TYPE(Student) student1,student2 声明变量 student1。 TYPE(Student),DIMENSION(100) ::class 声明派生类型数组class。 派生类型的变量声明类似于固有类型,在类型名称前添加 TYPE 关键字, 形式如下: TYPE(派生类型名) [[,属性] ::] 变量列表 派生类型成员可以和同类型的变量一样使用,但引用派生类型成员时, 须使用成员操作符%,例如: student1 % Birthdate = 461121 对派生类型变量 student1 的 Birthdate 成员进行赋值。 class % Female = .FALSE. 将数组 class 所有元素的 Female 成员设置为男性。 Student2 = Student1 将 Student1 的所有成员赋给 Student2 的对应成员,同一个派生 类型的2个变量可以相互赋值。
第六章
派生类型
固有数据类型,数组集合的元素要求类型相同。 用户定义类型或派生类型,Fortran 90 允许定义不同类型元 素的集合。
本章主要包括以下几个内容:
1 派生类型的定义 2 派生类型的构造及初始化 3 操作符重载 4 数据库管理应用
第一节
派生类型的定义
Fortran 90 允许由固有数据类型或其他派生类型创建新的派生类型, 将不同的类型元素定义为新的类型。比如要维护学生记录,学生的基 本信息可能包括姓名、学号、性别、出生年月、地址、电话号码、成 绩等,据此创建学生数据类型为: TYPE Student CHARACTER(20) Name !姓名 CHARACTER(10) No !学号 LOGICAL Female !性别 ! INTEGER BirthDate !出生年月 CHARACTER(20),DIMENSION(4) ::Address !地址 CHARACTER(10) Telephone !电话号码 REAL,DIMENSION(20) ::Marks !各科成绩 END TYPE
第二节
派生类型的构造及初始化
例6-1,定义一个简单的学生类型,用来说明派生类型的构造
MODULE Stu_Type !通常将类型声明置于模块内,派生类型模块 IMPLICIT NONE TYPE Student !定义派生类型 CHARACTER(20)NAME REAL Mark END TYPE END MODULE !在模块中定义派生类型 PROGRAM Main USE Stu_Type !引用定义的派生类型模块 IMPLICIT NONE TYPE(Student)::stu1=Student(“Smith,JR”,49),stu2 !在声明派生类型变量 stu1 时,用派生类型构造子对其初始化 PRINT*,‘输入stu2的成员:’ READ*,stu2 PRINT*,stu1,stu2,Student(“Bloggs”,50) END PROGRAM !在主程序中使用该派生类型,
派生类型构造子的形式为: d – name (expr - list)
d – name 指派生类型名; expr – list 为规定派生类型成员值的表达式列表,表达式的次序、类型、 种类数必须和定义派生类型成员的一致; 派生类型构造子可以出现在初始化中,也可以出现在赋值、输入/输出语 句中。 Fortran 95 允许在定义派生类型时,直接给出成员的默认值。如给出成 员 Mark 的默认值为60 : TYPE Student CHARACTER(20) NAME REAL :: Mark = 60 END TYPE 初始化时,成员的默认值将被构造子的表达式列表所覆盖,例如:
第三节
操作符重载
定义: 假如有某一派生类型的变量 a 和 b,要执行加法运算,我 们自然希望使用“+”运算符,写出表达式 “a+b”,但编译 时会出错,因为编译器不知道该如何完成这个加法操作 (Fortran 90 预定义运算符的运算对象只能是固有数据类 型),这时需要我们自己编写程序说明 “+” 在作用于该派 生类型的变量时,该实现什么样的功能,这就是操作符的 重载,或者是运算符重载。 分类: Fortran 90 的操作符重载,分为赋值操作符重载和其他操 作符重载。 说明: 操作符重载是对已有的操作符赋予多重含义,使同一操作 符作用于不同类型的数据时产生不同的行为。
ห้องสมุดไป่ตู้ 6-3 赋值操作符重载
MODULE StudentMod IMPLICIT NONE TYPE Student_Type CHARACTER(20)NAME REAL Mark END TYPE INTERFACE ASSIGNMENT(=) !接口块须以 ASSIGNMENT 命名 MODULE PROCEDURE Name_From_Student,Student_From_Name END INTERFACE CONTAINS 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
MODULE IntegerSets IMPLICIT NONE INTEGER, PARAMETER::MaxCard = 100 TYPE SET PRIVATE ! 规定成员在模块外不可访问 INTEGER Cardinality INTEGER, DIMENSION(MaxCard)::Members END TYPE SET 定义一个派生类型SET !定义一个派生类型 INTERFACE OPERATOR(.IN.) !接口块以 OPERATOR 命名,新定义操作符 命名, 接口块以 MODULE PROCEDURE MemberOf END INTERFACE
MODULE Stu_Type IMPLICIT NONE TYPE Student !定义Student数据类型 PRIVATE !成员私有,将成员的访问权限控制在模块内 CHARACTER(20)NAME REAL Mark END TYPE CONTAINS SUBROUTINE Student_(this,n,m) !相当于C++中的构造函数 TYPE(Student),INTENT(out)::this CHARACTER(*),INTENT(in)::n REAL,OPTIONAL,INTENT(in)::m this%Name=n IF(PRESENT(m))THEN this%Mark=m ELSE this%Mark=60 END IF END SUROUTINE
1. 赋值操作符重载
将姓名字符串直接赋给派生类型变量,如: stu = “Smith,JR” !stu 为 Student 派生类型变量 从派生类型变量中提取姓名,将派生类型变量直接赋给姓名字 符变量。如: StuName = stu ! StuName 为字符类型变量 以上操作中需要重新定义赋值操作符,使之可以处理字符类型 和派生类型组成的混合类型。 对第一种情况,需要编写带有两个虚参的子程序例程 (Student_From_Name),两个虚参分别为派生类型和字符类 型,其顺序必须和赋值表达式中出现的顺序相同。在该例程 中,需要显式地将字符参数赋给派生类型的姓名成员; 对第二种情况,是第一种情况的反操作,即子程序例程 (Name_From_Student)的两个虚参分别为字符类型和派生类 型,且将派生类型的姓名成员赋给字符参数。 详见例6-3
相关主题