Skip to content

Commit bde2de3

Browse files
authored
Create ch07-02-typeoverload.md
1 parent 7a8025c commit bde2de3

File tree

1 file changed

+146
-0
lines changed

1 file changed

+146
-0
lines changed

src/ch07-02-typeoverload.md

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
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

Comments
 (0)