C++实验报告

实验目的

编写一个名为Matrix的类,包括与2*2矩阵相关的字段,并实现特定功能,包括初始化为单位矩阵、重载运算符进行矩阵操作、链式操作、标量乘法、比较矩阵等。通过Matrix.h,Main.cpp中提供的main函数对Matrix类进行测试。

本篇实验在\(2*2\)的基础上进行改良,以\(n*n\)的矩阵进行呈现,以便有更好的扩展性。

实验过程

任务一:

创建一个matrix类,其中有设置了两个私有成员变量,一个是矩阵的阶数,另外一个则是存放矩阵的以vector实现的二维数组。

私有的好处一览:

① 优点 1:将所有成员属性设置为私有,可以自己控制读写权限。

② 优点 2:可以通过写权限,检测数据的有效性。

1
2
3
4
private:
int N;
std::vector<std::vector<int>> a;
};

任务二:

进行构造函数和析构函数的实现。

作用是:

① 构造函数:主要作用在于创建对象时为对象的成员属性赋值,构造函数由编译器自动调用,无须手动调用。

② 析构函数:主要作用在于对象销毁前系统自动调用,执行一些清理工作。

调用规则如下:

  1. 如果用户定义有参构造函数,C++ 不再提供默认无参构造,但是会提供默认拷贝构造。
  2. 如果用户定义拷贝函数,C++ 不会再提供其他构造函数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//默认构造函数
matrix(){}
//有参构造函数
matrix::matrix(int n)
{
this->N = n;
this->a = std::vector<std::vector<int>>(n + 1, std::vector<int>(n + 1, 0));
for (int i = 1; i <= n; i++)
{
this->a[i][i] = 1;
}
}
//析构函数
~matrix() {}

任务三:

实现加法,减法,乘法相应的运算符重载

采取全局函数搭配友元进行实现

友元的目的和相应用法

  1. 在程序里,有些私有属性,也想让类外特殊的一些函数或者类进行访问,就需要用到友元的技术。
  2. 友元的目的就是让一个函数或者类访问另一个类中私有成员。
  3. 友元的关键字为 friend。
  4. 友元的三种实现:
  1. 全局函数做友元。
  2. 类做友元。
  3. 成员函数做友元。

有一易错点,不能返回局部变量的引用,因为在创建完后会被销毁。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
// 矩阵加法实现
matrix operator+(const matrix &A, const matrix &B)
{
matrix temp(A.N);
for (int i = 1; i <= A.N; i++)
{
for (int j = 1; j <= A.N; j++)
{
temp.a[i][j] = A.a[i][j] + B.a[i][j];
}
}
return temp;
}

// 矩阵减法实现
matrix operator-(const matrix &A, const matrix &B)
{
matrix temp(A.N);
for (int i = 1; i <= A.N; i++)
{
for (int j = 1; j <= A.N; j++)
{
temp.a[i][j] = A.a[i][j] - B.a[i][j];
}
}
return temp;
}

// 矩阵乘法实现
matrix operator*(const matrix &A, const matrix &B)
{
matrix temp(A.N);
for (int i = 1; i <= A.N; i++)
{
temp.a[i][i] = 0;
}
for (int i = 1; i <= A.N; i++)
{
for (int j = 1; j <= A.N; j++)
{
for (int k = 1; k <= A.N; k++)
{
temp.a[i][j] += A.a[i][k] * B.a[k][j];
}
}
}
return temp;
}

// 矩阵数乘实现
matrix operator*(const matrix &A, const int &B)
{
matrix temp(A.N);
for (int i = 1; i <= A.N; i++)
{
for (int j = 1; j <= A.N; j++)
{
temp.a[i][j] = B * A.a[i][j];
}
}
return temp;
}

任务四

重载+=,-=,*=,=等运算符

具体实现采用成员函数的实现方法,深刻的体现了this指针中的两个作用中的第二个:

1.当形参和成员变量同名时,可用 this 指针来区分。 2.在类的非静态成员函数中返回对象本身,可使用 return * this。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
// 重载+=运算符
matrix &matrix::operator+=(const matrix &B)
{
int n = this->N;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
this->a[i][j] = this->a[i][j] + B.a[i][j];
}
}
return *this;
//返回本身,下同
}

// 重载-=运算符
matrix &matrix::operator-=(const matrix &B)
{
int n = this->N;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
this->a[i][j] = this->a[i][j] - B.a[i][j];
}
}
return *this;
}

// 重载*=运算符
matrix &matrix::operator*=(const matrix &B)
{
matrix temp(B.N);
int n = this->N;
for (int i = 1; i <= n; i++)
{
temp.a[i][i] = 0;
}
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
for (int k = 1; k <= n; k++)
{
temp.a[i][j] += this->a[i][k] * B.a[k][j];
}
}
}
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
this->a[i][j] = temp.a[i][j];
}
}
return *this;
}

任务五:

==,!=符号重载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// 重载等于运算符
bool matrix::operator==(const matrix &A)
{
int n = this->N;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
if (this->a[i][j] != A.a[i][j])
{
return 0;
}
}
}
return 1;
}

// 重载不等于号
bool matrix::operator!=(const matrix &A)
{
int n = this->N;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
if (this->a[i][j] != A.a[i][j])
{
return 1;
}
}
}
return 0;
}

任务六:

实现左移运算符重载和右移运算符重载

细节:

注意点:

  1. 只能通过全局函数进行重载,成员函数不能利用重载<<运算符,因为无法实现cout在左侧。

  2. 如果返回类型为void,那么就无法实现无限追加,也没有办法在后面添加换行符,因此需要传递引用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// 左移运算符重载
std::ostream &operator<<(std::ostream &out, const matrix &p)
{
out << "The order of a matrix is " << p.N << std::endl;
out << "The matrix is as follows " << std::endl;
for (int i = 1; i <= p.N; i++)
{
out << "|" << ' ';
for (int j = 1; j <= p.N; j++)
{
out << p.a[i][j] << " ";
}
out << "|"
<< " ";
out << std::endl;
}
out << "----------------------------------------------------" << std::endl;
//分隔符
return out;
//返回out以便实现无限追加
}

// 右移运算符重载
std::istream &operator>>(std::istream &cin, matrix &p)
{
std::cout << "please input your matrix order :" << std::endl;
cin >> p.N;
int n = p.N;
p.a = std::vector<std::vector<int>>(n + 1, std::vector<int>(n + 1, 0));
std::cout << "plaese input your matrix :" << std::endl;
for (int i = 1; i <= n; i++)
{
std::cout << "No." << i << ' ' << "row is:" << std::endl;
for (int j = 1; j <= n; j++)
{
cin >> p.a[i][j];
}
}
return cin;
}

代码以及测试代码实现如下:

Matrix.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include<iostream>
#include<vector>
#include<string>
class matrix
{
// 全局函数作为友元,以方便重载
//公有部分
public:
//重载左移运算符
friend std::ostream& operator<<(std::ostream& out, const matrix& p);
//重载右移运算符
friend std::istream& operator>>(std::istream& in, matrix& p);
//重载加法运算符
friend matrix operator+(const matrix& A, const matrix& B);
//重载减号运算符
friend matrix operator-(const matrix& A, const matrix& B);
//重载用于矩阵乘法的乘号运算符
friend matrix operator*(const matrix& A, const matrix& B);
//重载用以数乘的乘法运算符
friend matrix operator*(const matrix& A, const int& B);
// 默认构造函数
matrix();
// 0矩阵生成,这部分不予实现
/*
matrix(int n,int m)
{
this->N=n;
a = std::vector<std::vector<int>>(n + 1, std::vector<int>(n + 1, 0));
//直接生成一个0矩阵
}
*/
// 生成单位矩阵
matrix(int n);
// 重载等于运算符
bool operator==(const matrix& A);
// 重载不等于号
bool operator!=(const matrix& A);
// 重载赋值运算符
matrix& operator=(const matrix& A);
// 重载+=运算符
matrix& operator+=(const matrix& B);
// 重载-=运算符
matrix& operator-=(const matrix& B);
// 重载*=运算符
matrix& operator*=(const matrix& B);
//析构函数
~matrix() {}

//私有部分
private:
int N;
// 行与列
// 由于是方阵,只需要一个变量
std::vector<std::vector<int>> a;
// 二维数组
};

Matrix.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
#include<iostream>
#include<vector>
#include<string>
#include"Matrix.h"

matrix::matrix() {};

matrix::matrix(int n)
{
this->N = n;
this->a = std::vector<std::vector<int>>(n + 1, std::vector<int>(n + 1, 0));
for (int i = 1; i <= n; i++)
{
this->a[i][i] = 1;
}
}
// 重载等于运算符
bool matrix::operator==(const matrix& A)
{
int n = this->N;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
if (this->a[i][j] != A.a[i][j])
{
return 0;
}
}
}
return 1;
}

// 重载不等于号
bool matrix::operator!=(const matrix& A)
{
int n = this->N;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
if (this->a[i][j] != A.a[i][j])
{
return 1;
}
}
}
return 0;
}

// 重载赋值运算符
matrix& matrix::operator=(const matrix& A)
{
this->N = A.N;
int n = this->N;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
this->a[i][j] = A.a[i][j];
}
}
return *this;
}

// 重载+=运算符
matrix& matrix::operator+=(const matrix& B)
{
int n = this->N;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
this->a[i][j] = this->a[i][j] + B.a[i][j];
}
}
return *this;
}

// 重载-=运算符
matrix& matrix::operator-=(const matrix& B)
{
int n = this->N;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
this->a[i][j] = this->a[i][j] - B.a[i][j];
}
}
return *this;
}

// 重载*=运算符
matrix& matrix::operator*=(const matrix& B)
{
matrix temp(B.N);
int n = this->N;
for (int i = 1; i <= n; i++)
{
temp.a[i][i] = 0;
}
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
for (int k = 1; k <= n; k++)
{
temp.a[i][j] += this->a[i][k] * B.a[k][j];
}
}
}
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
this->a[i][j] = temp.a[i][j];
}
}
return *this;
}

// 矩阵加法实现
matrix operator+(const matrix& A, const matrix& B)
{
matrix temp(A.N);
for (int i = 1; i <= A.N; i++)
{
for (int j = 1; j <= A.N; j++)
{
temp.a[i][j] = A.a[i][j] + B.a[i][j];
}
}
return temp;
}

// 矩阵减法实现
matrix operator-(const matrix& A, const matrix& B)
{
matrix temp(A.N);
for (int i = 1; i <= A.N; i++)
{
for (int j = 1; j <= A.N; j++)
{
temp.a[i][j] = A.a[i][j] - B.a[i][j];
}
}
return temp;
}

// 矩阵乘法实现
matrix operator*(const matrix& A, const matrix& B)
{
matrix temp(A.N);
for (int i = 1; i <= A.N; i++)
{
temp.a[i][i] = 0;
}
for (int i = 1; i <= A.N; i++)
{
for (int j = 1; j <= A.N; j++)
{
for (int k = 1; k <= A.N; k++)
{
temp.a[i][j] += A.a[i][k] * B.a[k][j];
}
}
}
return temp;
}

// 矩阵数乘实现
matrix operator*(const matrix& A, const int& B)
{
matrix temp(A.N);
for (int i = 1; i <= A.N; i++)
{
for (int j = 1; j <= A.N; j++)
{
temp.a[i][j] = B * A.a[i][j];
}
}
return temp;
}

// 左移运算符重载
std::ostream& operator<<(std::ostream& out, const matrix& p)
{
out << "The order of a matrix is " << p.N << std::endl;
out << "The matrix is as follows " << std::endl;
for (int i = 1; i <= p.N; i++)
{
out << "|" << ' ';
for (int j = 1; j <= p.N; j++)
{
out << p.a[i][j] << " ";
}
out << "|"
<< " ";
out << std::endl;
}
out << "----------------------------------------------------" << std::endl;
return out;
}

// 右移运算符重载
std::istream& operator>>(std::istream& cin, matrix& p)
{
std::cout << "please input your matrix order :" << std::endl;
cin >> p.N;
int n = p.N;
p.a = std::vector<std::vector<int>>(n + 1, std::vector<int>(n + 1, 0));
std::cout << "plaese input your matrix :" << std::endl;
for (int i = 1; i <= n; i++)
{
std::cout << "No." << i << ' ' << "row is:" << std::endl;
for (int j = 1; j <= n; j++)
{
cin >> p.a[i][j];
}
}
return cin;
}

main.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#include <iostream>
#include<string>
#include"Matrix.h"
int main()
{
std::cout << "Now let us start our testing phase" << std::endl;
std::cout << "ouput an identity matrix" << std::endl;
matrix a(2);
std::cout << a;
std::cout << "Enter two test matrices" << std::endl;
std::cin >> a;
std::cout << a;
matrix b(2);
std::cin >> b;
std::cout << b;
std::cout << "Enter the phase of checking addition, subtraction and multiplication of the two matrices" << std::endl;
matrix c = a + b;
std::cout << c << std::endl;
c = a - b;
std::cout << c << std::endl;
c = a * b;
std::cout << c << std::endl;
std::cout << "Next is the scalar multiplication";
int x = 2;
c = a * x;
std::cout << c << std::endl;
std::cout << "Enter the phase of comparing whether the two matrices are equal or not " << std::endl;
if (a == b)
{
std::cout << "Matrix a is equal to matrix b" << std::endl;
}
else
{
std::cout << "Matrix a is unequal to matrix b" << std::endl;
}
if (a != b)
{
std::cout << "Matrix a is unequal to matrix b" << std::endl;
}
else
{
std::cout << "Matrix a is equal to matrix b" << std::endl;
}
std::cout << "Proceed to +=, -=, *= part" << std::endl;
a += b;
std::cout << a << std::endl;
a -= b;
std::cout << a << std::endl;
std::cout << b << std::endl;
a *= b;
std::cout << a << std::endl;
std::cout << "Finally, verify if chain addition is possible" << std::endl;
std::cout << a + b + a << std::endl;
return 0;
}

实验结果

实验结果通过实现单位矩阵,并传递两个三维方阵进行实现一系列的运算,检验程序的正确新和稳健性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
Now let us start our testing phase
ouput an identity matrix
The order of a matrix is 2
The matrix is as follows
| 1 0 |
| 0 1 |
----------------------------------------------------
Enter two test matrices
please input your matrix order :
3
plaese input your matrix :
No.1 row is:
1 2 3
No.2 row is:
4 5 6
No.3 row is:
7 8 9
The order of a matrix is 3
The matrix is as follows
| 1 2 3 |
| 4 5 6 |
| 7 8 9 |
----------------------------------------------------
please input your matrix order :
3
plaese input your matrix :
No.1 row is:
4 5 6
No.2 row is:
1 2 3
No.3 row is:
3 6 7
The order of a matrix is 3
The matrix is as follows
| 4 5 6 |
| 1 2 3 |
| 3 6 7 |
----------------------------------------------------
Enter the phase of checking addition, subtraction and multiplication of the two matrices
The order of a matrix is 3
The matrix is as follows
| 5 7 9 |
| 5 7 9 |
| 10 14 16 |
----------------------------------------------------

The order of a matrix is 3
The matrix is as follows
| -3 -3 -3 |
| 3 3 3 |
| 4 2 2 |
----------------------------------------------------

The order of a matrix is 3
The matrix is as follows
| 15 27 33 |
| 39 66 81 |
| 63 105 129 |
----------------------------------------------------

Next is the scalar multiplicationThe order of a matrix is 3
The matrix is as follows
| 2 4 6 |
| 8 10 12 |
| 14 16 18 |
----------------------------------------------------

Enter the phase of comparing whether the two matrices are equal or not
Matrix a is unequal to matrix b
Matrix a is unequal to matrix b
Proceed to +=, -=, *= part
The order of a matrix is 3
The matrix is as follows
| 5 7 9 |
| 5 7 9 |
| 10 14 16 |
----------------------------------------------------

The order of a matrix is 3
The matrix is as follows
| 1 2 3 |
| 4 5 6 |
| 7 8 9 |
----------------------------------------------------

The order of a matrix is 3
The matrix is as follows
| 4 5 6 |
| 1 2 3 |
| 3 6 7 |
----------------------------------------------------

The order of a matrix is 3
The matrix is as follows
| 15 27 33 |
| 39 66 81 |
| 63 105 129 |
----------------------------------------------------

Finally, verify if chain addition is possible
The order of a matrix is 3
The matrix is as follows
| 34 59 72 |
| 79 134 165 |
| 129 216 265 |
----------------------------------------------------


请按任意键继续. . .

心得体会

通过本次实验,我对C++类与对象的使用更加得心应手,并且学会了this指针的核心用法和相关的vector知识。同时我对已有的运算符进行重载,赋予其另一种功能,以适应不同的数据类型这一内核有了更深的理解。