CPP Matrix
CPP Matrix
Todays Lecture
Remember the Big Four member methods of a C++ class: class Foo { public: Foo(); //default constructor Foo(const Foo & f); //copy constructor ~Foo(); //destructor Foo& Foo::operator=(const Foo& rhs); //copy assignment } We will illustrate these with a class Matrix. A Matrix will be a dynamic two-dimensional array.
CS410 Software Engineering C++: Matrix example 2
Matrix Constructor
// Dynamically allocate a sizeX sizeY matrix, // initialized to all 0 entries Matrix::Matrix(int sizeX, int sizeY) : dx(sizeX),dy(sizeY) { allocArrays(); for (int i = 0; i < dx; i++) { for (int j = 0; j < dy; j++) { p[i][j] = 0; } } }
CS410 Software Engineering C++: Matrix example 6
Matrix Destructor
Matrix::~Matrix() { for (int i = 0; i < dx; i++) { delete [] p[i]; } delete [] p; }
for (int i = 0; i < dx; i++) { for (int j = 0; j < dy; j++) { p[i][j] = m.p[i][j]; } } return *this; }
10
The code makes this have the same contents as the rhs. So why not return void? Answer: x = y = z, which is parsed as x = (y = z)
11
12
Matrix Addition
Matrix& Matrix::operator+=(const Matrix& m) { // x+=y adds the y-entries into the x-entries for (int i=0; i<dx; ++i) { for (int j=0; j<dy; ++j) { p[i][j] += m.p[i][j]; } } return *this; }
CS410 Software Engineering C++: Matrix example 14
Matrix Addition
Matrix Matrix::operator+(const Matrix& m) { Matrix temp(*this); //copy constructor return (temp += m); } The assignment form, +=, does the real work. The copy constructor does the allocation. This trick is less useful for matrix multiplication.
CS410 Software Engineering C++: Matrix example 15
+, +=, and =
In C++, defining operator+ and operator= does not automatically give the right meaning to +=. This language-design bug is fixed in C#.
16
Matrix Output
ostream &operator<< (ostream &out, const Matrix &m) { for (int i = 0; i < m.dx; ++i) { for (int j = 0; j < m.dx; ++j) out << m.p[i][j] << " "; out << endl; } return out; }
CS410 Software Engineering C++: Matrix example 18
19
Matrix Multiplication
We conclude with matrix multiplication. We want to be able to write two kinds of statements: matProduct = mat1 * mat2; matDouble = 2 * mat1; We write two ordinary, non-member functions, and let ordinary overloading pick the right one.
22
Matrix Multiplication
class Matrix { public: friend Matrix operator* (const Matrix & m1, const Matrix & m2); friend Matrix operator* (long c, const Matrix & m2); friend Matrix operator* (const Matrix & m1, long c); };
23
Matrix Multiplication
Matrix operator*(const Matrix& m1, const Matrix& m2) { Matrix prod(m1.dx, m2.dy); x = for (int i=0; i<prod.dx; ++i) { for (int j=0; j<prod.dy; ++j) { for (int k=0; k<m1.dy; ++k) { prod.p[i][j] += m1.p[i][k] * m2.p[k][j]; } } } return prod; }
CS410 Software Engineering C++: Matrix example 24
Matrix Multiplication
Matrix operator*(long c, const Matrix& m2) { Matrix prod(m2); for (int i=0; i<prod.dx; ++i) { for (int j=0; j<prod.dy; ++j) { prod.p[i][j] = c * m2.p[i][j]; } } return prod; } Matrix operator*(const Matrix& m2, long c) { return c*m2; }
CS410 Software Engineering C++: Matrix example 25
Output
Matrix x 1 2 Matrix y 3 4 Matrix z 0 x*y = 3 4 6 8
CS410 Software Engineering C++: Matrix example 27
Final Remarks
The full code Matrix.cpp is in the Examples section (see the course homepage) ALL the code should have had error checking, for example: assert(sizeX > 0); if (m1.dy != m2.dx) throw MatMulException(); The on-line copy of Matrix.cpp has asserts. We didnt code *= for matrices; this is left as an exercise. Another exercise: define a class BinaryTree, and figure out what overloaded operators should be defined for it. (BinTree x = y + z ?)
CS410 Software Engineering C++: Matrix example 28
Appendix
The class version of this Powerpoint file had a couple of bugs. These bugs are instructive, especially for those with a Java background. Hence this appendix. We have three places in the code where we need to allocate the arrays p and the p[i] arrays: Matrix(int sizeX, int sizeY); //constructor Matrix(const Matrix& m); //copy constructor
Appendix
We'd like to reuse the code that does these allocations. Above, I've introduced the private method allocArrays() to do this. In Java and in C#, one constructor can call another constructor in the same class:
Appendix
I tried to do something similar:
31
Appendix
In operator=, I tried: if (dx != m.dx || dy != m.dy) { this->~Matrix(); legal! And does the right thing. Matrix(m.dx, m.dy); Legal, but just creates an } anonymous Matrix
object doesn't affect "this"