实现一个矩阵类,重载下标操作符, 即 m[i][j], 以及其它运算符
1:
2: //重载下标操作符, m[i][j], 方法1:
3: #pragma once
4: #include <iostream>
5: #include <cstddef>
6: #include <cassert>
7:
8: template<typename T, std::size_t ROW = 10, std::size_t COLUMN = 10>
9: class Matrix
10: {
11: private:
12: std::size_t _ROW;
13: std::size_t _COLUMN;
14: T* pData;
15:
16: public:
17: Matrix();
18: Matrix(std::size_t M, std::size_t N);
19: ~Matrix();
20:
21: //重载下标运算符,实现 a[m][n]
22: T* operator[](std::size_t m);
23: const T* operator[](std::size_t m) const;
24:
25: //提供 a(m, n) 这样的操作
26: T& operator()(std::size_t m, std::size_t n);
27: const T& operator()(std::size_t m, std::size_t n) const;
28:
29: //拷贝构造
30: Matrix(const Matrix<T>& m);
31: //重载 =
32: Matrix<T>& operator=(const Matrix<T>& m);
33:
34: //重载 +=
35: Matrix<T>& operator+=(const Matrix<T>& m);
36:
37: //重载 +, -, *
38: Matrix<T> operator+(const Matrix<T>& m);
39: Matrix<T> operator-(const Matrix<T>& m);
40: Matrix<T> operator*(const Matrix<T>& m);
41:
42: //矩阵转置 !
43: Matrix<T> operator!();
44:
45: //求反 -
46: Matrix<T>& operator-();
47:
48: //显示矩阵
49: void displayMatrix() const;
50:
51: //取得行, 列的大小
52: const std::size_t getRow() const;
53: const std::size_t getColumn() const;
54:
55: //注: 重载 << 时, template<typename T1> 必须和 模板类中的类型不一样
56: template<typename T1>
57: friend std::ostream& operator<<(std::ostream& os, const Matrix<T1>& m);
58: };
59:
60: //默认构造函数
61: template<typename T, std::size_t ROW, std::size_t COLUMN>
62: Matrix<T, ROW, COLUMN>::Matrix():_ROW(ROW),_COLUMN(COLUMN)
63: {
64: pData = new T[_ROW*_COLUMN];
65: assert(pData);
66: memset(pData, 0, _ROW*_COLUMN*sizeof(T));
67: }
68: //有参构造函数
69: template<typename T, std::size_t ROW, std::size_t COLUMN>
70: Matrix<T, ROW, COLUMN>::Matrix(std::size_t M, std::size_t N)
71: :_ROW(M), _COLUMN(N)
72: {
73: pData = new T[_ROW*_COLUMN];
74: assert(pData);
75: memset(pData, 0, _ROW*_COLUMN*sizeof(T));
76: }
77:
78: //析构函数
79: template<typename T, std::size_t ROW, std::size_t COLUMN>
80: Matrix<T, ROW, COLUMN>::~Matrix()
81: {
82: if(pData)
83: delete []pData;
84: pData = NULL;
85: }
86: //拷贝构造
87: template<typename T, std::size_t ROW, std::size_t COLUMN>
88: Matrix<T, ROW, COLUMN>::Matrix(const Matrix<T>& m)
89: {
90: _ROW = m.getRow();
91: _COLUMN = m.getColumn();
92: pData = new T[_ROW*_COLUMN];
93: assert(pData);
94: memcpy(pData, m.pData, _ROW*_COLUMN*sizeof(T));
95: }
96: //重载下标操作符
97: //a[m][n], a[m] 首先调用此重载运算符, 返回指针 (pData + m*_COLUMN)
98: //然后进行正常的指针运算 (pData + m*_COLUMN)[n]
99: template<typename T, std::size_t ROW, std::size_t COLUMN>
100: T* Matrix<T, ROW, COLUMN>::operator[](std::size_t m)
101: {
102: assert(m >= 0 && m < _ROW);
103: return (pData + m*_COLUMN);
104: }
105: //for const class
106: template<typename T, std::size_t ROW, std::size_t COLUMN>
107: const T* Matrix<T, ROW, COLUMN>::operator[](std::size_t m) const
108: {
109: assert(m >= 0 && m < _ROW);
110: return (pData + m*_COLUMN);
111: //return operator[](m);
112: }//*/
113: //a(m,n)
114: template<typename T, std::size_t ROW, std::size_t COLUMN>
115: T& Matrix<T, ROW, COLUMN>::operator()(std::size_t m, std::size_t n)
116: {
117: assert(m < _ROW && m >= 0 && n < _COLUMN && n >= 0);
118: return (pData + m*_COLUMN)[n];
119: }
120: //for const class
121: template<typename T, std::size_t ROW, std::size_t COLUMN>
122: const T& Matrix<T, ROW, COLUMN>::operator()
123: (std::size_t m, std::size_t n) const
124: {
125: assert(m < _ROW && m >= 0 && n < _COLUMN && n >= 0);
126: return (pData + m*_COLUMN)[n];
127: }//*/
128:
129: //查看行列值
130: template<typename T, std::size_t ROW, std::size_t COLUMN>
131: const std::size_t Matrix<T, ROW, COLUMN>::getRow() const
132: {
133: return _ROW;
134: }
135: template<typename T, std::size_t ROW, std::size_t COLUMN>
136: const std::size_t Matrix<T, ROW, COLUMN>::getColumn() const
137: {
138: return _COLUMN;
139: }
140:
141: //输出整个矩阵
142: template<typename T, std::size_t ROW, std::size_t COLUMN>
143: void Matrix<T, ROW, COLUMN>::displayMatrix() const
144: {
145: std::cout << std::endl << "Now The Matrix is: " << std::endl;
146: for(std::size_t i = 0; i < _ROW; i++)
147: for(std::size_t j = 0; j < _COLUMN; j++)
148: {
149: std::cout << *(pData+i*_COLUMN+j) << " ";
150: if(j == _COLUMN - 1)
151: std::cout << std::endl;
152: }
153: std::cout << std::endl;
154: }
155: //重载 =
156: template<typename T, std::size_t ROW, std::size_t COLUMN>
157: Matrix<T>& Matrix<T, ROW, COLUMN>::operator=(const Matrix<T>& m)
158: {
159: if(this == &m)
160: return *this;
161: assert(_ROW == m.getRow() && _COLUMN == m.getColumn());
162: for(std::size_t i = 0; i < _ROW; i++)
163: for(std::size_t j = 0; j < _COLUMN; j++)
164: {
165: operator()(i, j) = m(i, j);
166: }
167:
168: return *this;
169: }
170: //重载 +=
171: template<typename T, std::size_t ROW, std::size_t COLUMN>
172: Matrix<T>& Matrix<T, ROW, COLUMN>::operator+=(const Matrix<T>& m)
173: {
174: assert(_ROW == m.getRow() && _COLUMN == m.getColumn());
175: for(std::size_t i = 0; i < _ROW; i++)
176: for(std::size_t j = 0; j < _COLUMN; j++)
177: {
178: operator()(i, j) += m(i, j);
179: }
180: return *this;
181: }
182: //operator+(const Matrix<T>& m)
183: template<typename T, std::size_t ROW, std::size_t COLUMN>
184: Matrix<T> Matrix<T, ROW, COLUMN>::operator+(const Matrix<T>& m)
185: {
186: assert(_ROW == m.getRow() && _COLUMN == m.getColumn());
187: Matrix<T, ROW, COLUMN> matrix;
188: for(std::size_t i = 0; i < _ROW; i++)
189: for(std::size_t j = 0; j < _COLUMN; j++)
190: {
191: matrix(i, j) = operator()(i, j) + m(i, j);
192: }
193: return matrix;
194: }
195: //operator-()
196: template<typename T, std::size_t ROW, std::size_t COLUMN>
197: Matrix<T>& Matrix<T, ROW, COLUMN>::operator-()
198: {
199: for(std::size_t i = 0; i < _ROW; i++)
200: for(std::size_t j = 0; j < _COLUMN; j++)
201: {
202: operator()(i, j) = -operator()(i, j);
203: }
204: return *this;
205: }
206: //operator*()
207: template<typename T, std::size_t ROW, std::size_t COLUMN>
208: Matrix<T> Matrix<T, ROW, COLUMN>::operator*(const Matrix<T>& m)
209: {
210: assert(_ROW == m.getRow() && _COLUMN == m.getColumn());
211: Matrix<T, ROW, COLUMN> matrix;
212: for(std::size_t i = 0; i < _ROW; i++)
213: for(std::size_t j = 0; j < _COLUMN; j++)
214: {
215: matrix(i, j) = operator()(i, j) * m(i, j);
216: }
217: return matrix;
218: }
219: //矩阵转置 operator!()
220: template<typename T, std::size_t ROW, std::size_t COLUMN>
221: Matrix<T> Matrix<T, ROW, COLUMN>::operator!()
222: {
223: Matrix<T, ROW, COLUMN> matrix;
224: for(std::size_t i = 0; i < _ROW; i++)
225: for(std::size_t j = 0; j < _COLUMN; j++)
226: {
227: matrix(i, j) = (*this)(j, i);
228: }
229: return matrix;
230: }
231:
232: //for cout << matrix;
233: template<typename T1>
234: std::ostream& operator<<(std::ostream& os, const Matrix<T1>& m)
235: {
236: if(m.getRow() <= 0 || m.getColumn() <= 0)
237: return os;
238: for(std::size_t i = 0; i < m.getRow(); i++)
239: for(std::size_t j = 0; j < m.getColumn(); j++)
240: {
241: os << m(i, j) << " ";
242: if(j == m.getColumn() - 1)
243: os << std::endl;
244: }
245: return os;
246: }
1: //重载下标操作符, m[i][j], 方法2:
2: //使用代理类. 定义两个类,当第一个类调用重载的操作符时,使此函数返回
3: //第二个类的对象,在第二个类中,同样定义了运算符 [] 重载。但在第一个
4: //类中的重载操作符要能访问第二个类的私有成员,那么就应该把第一个类声明
5: //为第二个类的友元。
6: //----
7: //每个MatrixBody对象扮演的是一个一维数组,而这个一维数组没有在使用Matrixs的
8: //程序中出现。扮演其它对象的对象通常被称为代理类。在这个例子里,MatrixBody是
9: //一个代理类。它的实例扮演的是一个在概念上不存在的一维数组。
10: //代理类的概念见: More Effective C++ Item M30:代理类
11: #pragma once
12: #include <iostream>
13: #include <cstddef>
14: #include <cassert>
15:
16: template <typename T>
17: class Matrixs
18: {
19: class MatrixBody
20: {
21: friend class Matrixs<T>;
22: private:
23: T* _pData;
24: std::size_t _Rows;
25: std::size_t _Column;
26: std::size_t _CurrentRow; //当前行
27:
28: MatrixBody(std::size_t row, std::size_t column);
29:
30: public:
31: T& operator[](std::size_t j);
32: const T& operator[](std::size_t j) const;
33: ~MatrixBody();
34: }mBody;
35:
36: public:
37: Matrixs(std::size_t row, std::size_t column)
38: :mBody(row, column)
39: { }
40:
41:
42: //[] 返回第二个类的对象
43: MatrixBody& operator[](std::size_t i);
44: const MatrixBody& operator[](std::size_t i) const;
45:
46: //输出矩阵内容
47: void displayMatrix() const;
48:
49: };
50:
51: //代理类构造函数
52: template <typename T>
53: Matrixs<T>::MatrixBody::MatrixBody(std::size_t row, std::size_t column)
54: {
55: _Rows = row;
56: _Column = column;
57: _CurrentRow = -1;
58: _pData = new T[_Rows*_Column];
59: assert(_pData != NULL);
60: memset(_pData, 0, _Rows*_Column*sizeof(T));
61: }
62: //代理类的下标重载符
63: template <typename T>
64: T& Matrixs<T>::MatrixBody::operator[](std::size_t j)
65: {
66: bool row_error = false;
67: bool column_error = false;
68: try
69: {
70: if(_CurrentRow < 0 || _CurrentRow >= _Rows)
71: row_error = true;
72: if(j < 0 || j >= _Column)
73: column_error = true;
74: if(row_error || column_error)
75: throw 'e';
76: }
77: catch(char)
78: {
79: if(row_error)
80: cerr << "Row access invalid!" << _CurrentRow << endl;
81: if(column_error)
82: cerr << "Column access invalid!" << j << endl;
83: }
84:
85: return _pData[_CurrentRow*_Column + j];
86: }
87:
88: //代理类析构函数
89: template <typename T>
90: Matrixs<T>::MatrixBody::~MatrixBody()
91: {
92: if(_pData != NULL)
93: delete []_pData;
94: _pData = NULL;
95: }
96:
97: //矩阵类下标重载符[] //模板的语法实在是太奇怪了,注意下面必须有 typename
98: template<typename T>
99: typename Matrixs<T>::MatrixBody& Matrixs<T>::operator[](std::size_t i)
100: {
101: mBody._CurrentRow = i;
102: return mBody;
103: }
104:
105: template <typename T>
106: const typename Matrixs<T>::MatrixBody& Matrixs<T>::operator[](std::size_t i) const
107: {
108: mBody._CurrentRow = i;
109: return mBody;
110: //operator[](i);
111: }
112:
113: //输出矩阵内容
114: template <typename T>
115: void Matrixs<T>::displayMatrix() const
116: {
117: std::cout << std::endl << "Now The Matrix is: " << std::endl;
118: for(std::size_t i = 0; i < mBody._Rows; i++)
119: {
120: for(std::size_t j = 0; j < mBody._Column; j++)
121: {
122: std::cout << *(mBody._pData+i*mBody._Column+j) << " ";
123:
124: if(j == mBody._Column - 1)
125: std::cout << std::endl;
126: }
127: }
128: std::cout << std::endl;
129: }
1: //test for Matrix class
2: #include "MatrixClass.h"
3: #include "MatrixClass1.h"
4: #include <iostream>
5:
6: int main()
7: {
8:
9: //指定矩阵大小
10: Matrix<int, 6, 5> matrix;
11: std::cout << "ROW = " << matrix.getRow() << " "
12: << "COLUMN = " << matrix.getColumn() << std::endl;
13: matrix.displayMatrix();
14: matrix[1][2] = 5;
15: std::cout << "matirx[1][2] = " << matrix[1][2] << std::endl;
16: matrix[5][4] = 6;
17: std::cout << "matirx[5][4] = " << matrix[5][4] << std::endl;
18: //matrix[6][4] = 3; //溢出
19: matrix.displayMatrix();
20: matrix(3, 3) = matrix[5][4];
21: matrix.displayMatrix();
22:
23: //采用默认构造参数,默认大小
24: Matrix<int> matrix1;
25: matrix.displayMatrix();
26: matrix1[3][4] = 5;
27: std::cout << "ROW = " << matrix1.getRow() << " "
28: << "COLUMN = " << matrix1.getColumn() << std::endl;
29: std::cout << "matirx1[3][4] = " << matrix1[3][4] << std::endl;
30: std::cout << "matirx1[3][3] = " << matrix1[3][3] << std::endl;
31: matrix1.displayMatrix();//*/
32:
33: //test for +=
34: Matrix<int> matrix2;
35: matrix2[3][4] = 2;
36: matrix2[1][4] = 3;
37: matrix2.displayMatrix();
38: std::cout << "Test for the operator+=(): ";
39: matrix2 += matrix1; //*/
40: matrix2.displayMatrix();
41:
42: //test for operator-()
43: std::cout << "Test for operator-(): ";
44: -matrix2;
45: matrix2.displayMatrix();
46:
47: //test for opeartor+() and =
48: std::cout << "Test for operator+() and operator=(): ";
49: matrix1 = matrix2;
50: matrix1 = matrix1 + matrix2;
51: matrix1.displayMatrix();
52:
53: //test for opeartor!()
54: std::cout << "Test for operator!(): ";
55: matrix2 = !matrix1;
56: matrix2.displayMatrix();
57:
58: std::cout << "Test for cout << matrix : " << std::endl;;
59: std::cout << matrix2 << endl;
60:
61: //测试代理类
62: std::cout << "Test for the proxy class: ";
63: Matrixs<int> a(5,5);
64: a.displayMatrix();
65: a[2][1] = 3;
66: a.displayMatrix();
67:
68: return 0;
69: }
使用 C++ 实现二维数组, 主要有如下不同的方法,程序中使用的是第一种:
//不同的方法创建一个 m[3][5]
//1):
int* m1 = new int[3*5];
delete []m1;
//点:调用不够直观
//优点:连续储存,n 可以不是已知
//2):
int (*m2)[5] = new int[3][5];
delete []m2;
//缺点:n 必须是已知
//优点:调用直观,连续储存,程序简洁(经过测试,析构函数能正确调用)
//3):
int** m3 = new int*[3];
for(int i = 0; i < 3; i++)
m3[i] = new int[5];
for(int i = 0; i < 3; i++)
delete []m3[i];
delete []m3;
//缺点:非连续储存,程序烦琐,m3 为 A** 类型
//优点:调用直观,n 可以不是已知
//4):
vector< vector<int> > m4;
m4.resize(3);
for(int i = 0; i < 5; i++)
m4.resize(5);
//缺点:非连续储存,调试不够方便,编译速度下降,程序膨胀(实际速度差别不大)
//优点:调用直观,自动析构与释放内存,可以调用 stl 相关函数,动态增长
//5):
vector< vector<int> > m5;
m5.resize(3*5);
//方法 1, 4 的结合
//6): 3) 的改进
int** m6 = new int*[3];
m6[0] = new int[3*5];
for(int i = 1; i < 3; i++)
m6[i] = m6[i-1] + 5;
//优点: 连续存储, n 可以不是已知, 析构方便