|
| 1 | +# 自定义类型的重载 |
| 2 | + |
| 3 | +## 函数重载 |
| 4 | + |
| 5 | +当定义的函数很多的时候,函数名会非常复杂,有时候我们希望可以简化,这时候,使用重载是一个选择。例如对于`vector`类型,我们希望它也可以通过传入一个数组来初始化。使用`generic`关键字就可以对函数进行重载 |
| 6 | + |
| 7 | +``` fortran |
| 8 | +module vector_mod |
| 9 | + implicit none |
| 10 | + type vector_t |
| 11 | + real,allocatable::x(:) |
| 12 | + contains |
| 13 | + generic::init=>vector_init,vector_init_array |
| 14 | + procedure,pass:: vector_init,vector_init_array |
| 15 | + end type vector_t |
| 16 | +contains |
| 17 | + subroutine vector_init(this,n) |
| 18 | + class(vector_t),intent(inout)::this |
| 19 | + integer,intent(in)::n |
| 20 | + allocate(this%x(n)) |
| 21 | + end subroutine vector_init |
| 22 | +
|
| 23 | + subroutine vector_init_array(this,a) |
| 24 | + class(vector_t),intent(inout)::this |
| 25 | + real,intent(in)::a(:) |
| 26 | + allocate(this%x,source=a) |
| 27 | + end subroutine vector_init_array |
| 28 | +end module vector_mod |
| 29 | +
|
| 30 | +program main |
| 31 | + use vector_mod |
| 32 | + implicit none |
| 33 | + type(vector_t)::v |
| 34 | + type(vector_t)::va |
| 35 | + call v%init(10) |
| 36 | + call va%init([real::1,2,3,4]) |
| 37 | +end program main |
| 38 | +``` |
| 39 | +此时使用两种方式均可以对其进行初始化。 |
| 40 | + |
| 41 | +## 运算符重载 |
| 42 | + |
| 43 | +有时候,我们也希望对内置的运算符进行重载,用来提高代码的一致性。例如我们有一个分数类型,它有`+-*/`和`**`的操作,但是如果使用过程绑定的函数则显得代码过于臃肿。此时就可以使用运算符重载 |
| 44 | + |
| 45 | +``` fortran |
| 46 | +module frac_mod |
| 47 | + implicit none |
| 48 | + type frac |
| 49 | + integer(8)::num!numerator |
| 50 | + integer(8)::den!denominator |
| 51 | + contains |
| 52 | + generic::operator(.reduce.)=>cancelling !也可以使用自定义运算符 |
| 53 | + generic::operator(+)=>add,add_frac_num,add_num_frac |
| 54 | + !generic::operator(-)=>sub |
| 55 | + !generic::operator(*)=>mult |
| 56 | + !generic::operator(/)=>div |
| 57 | + !generic::operator(**)=>pow |
| 58 | + ! |
| 59 | + procedure,pass ::add,add_frac_num |
| 60 | + procedure,pass(this)::add_num_frac |
| 61 | + procedure,pass ::cancelling |
| 62 | + !procedure,pass::sub |
| 63 | + !procedure,pass::mult |
| 64 | + !procedure,pass::divi |
| 65 | + end type |
| 66 | +contains |
| 67 | + elemental function cancelling(this)result(z) |
| 68 | + class(frac),intent(in)::this |
| 69 | + type(frac) ::z |
| 70 | + ! do something |
| 71 | + end function cancelling |
| 72 | +
|
| 73 | + type(frac) elemental function add(this,y)result(z) |
| 74 | + class(frac),intent(in)::this,y |
| 75 | + z%num=this%num*y%den+y%num*this%den |
| 76 | + z%den=this%den*y%den |
| 77 | + end function add |
| 78 | +
|
| 79 | + type(frac) elemental function add_frac_num(this,m)result(z) |
| 80 | + class(frac),intent(in)::this |
| 81 | + integer,intent(in) ::m |
| 82 | + z%num=this%num+this%den * m |
| 83 | + z%den=this%den |
| 84 | + end function add_frac_num |
| 85 | +
|
| 86 | + type(frac) elemental function add_num_frac(m,this)result(z) |
| 87 | + class(frac),intent(in)::this |
| 88 | + integer,intent(in) ::m |
| 89 | + z%num=this%num+this%den * m |
| 90 | + z%den=this%den |
| 91 | + end function add_num_frac |
| 92 | +end module frac_mod |
| 93 | +
|
| 94 | +program main |
| 95 | + use frac_mod |
| 96 | + implicit none |
| 97 | + type(frac)::x,y,z,w(2) |
| 98 | + x=frac(1,2) |
| 99 | + y=frac(2,3) |
| 100 | + w=[frac(1,4),frac(1,3)] !自定义类型数组初始化 |
| 101 | + z=x+y |
| 102 | + write(*,*)z |
| 103 | + z=x+1 |
| 104 | + write(*,*)z |
| 105 | + z=2+y |
| 106 | + write(*,*)z |
| 107 | + write(*,*)w+2 !也支持数组 |
| 108 | +end program main |
| 109 | +``` |
| 110 | +- 除此之外,也可以对比较运算符进行重载,注意比较运算符中运算符和其对应的旧形式属于同一个函数,不能重载为不同的功能。 |
| 111 | + |
| 112 | +## 赋值运算符的重载 |
| 113 | + |
| 114 | +赋值的运算符具有特有的形式`assignment(=)` |
| 115 | + |
| 116 | +``` fortran |
| 117 | +module string_mod |
| 118 | + implicit none |
| 119 | + type string |
| 120 | + character(:),allocatable::str |
| 121 | + contains |
| 122 | + generic::assignment(=)=>equal |
| 123 | + procedure,pass::equal |
| 124 | + end type string |
| 125 | +contains |
| 126 | + subroutine equal(this,s) |
| 127 | + class(string),intent(inout)::this |
| 128 | + character(len=*),intent(in)::s |
| 129 | + this%str=s |
| 130 | + end subroutine equal |
| 131 | +end module string_mod |
| 132 | +
|
| 133 | +program main |
| 134 | + use string_mod |
| 135 | + implicit none |
| 136 | + type(string)::s |
| 137 | + s="123" |
| 138 | + !内置构造函数形式 |
| 139 | + s=string("456") |
| 140 | +end program main |
| 141 | +``` |
| 142 | + |
| 143 | +## 习题 |
| 144 | +- 请你尝试补充完所有的运算符 |
| 145 | +- 尝试加入`gcd`对分数进行约分,补充`.reduce.`函数 |
| 146 | +- (附加题)完成分数类,并使用高斯消元法求解希尔伯特矩阵的行列式和逆矩阵 |
0 commit comments