CIS-3012 Homework #3: Class Matrix

Due: Wednesday, October 25, 2023

Reading: Chapter 13 in the primary text on copy control.

Part 1

The attached file, homework-03.zip, contains a definition of a simple Matrix class and the start of a Matrix demonstration program. A few of the methods are already implemented. For this assignment, you are to implement the remaining methods and free functions in Matrix.hpp (the reason everything should be implemented in the header file is related to templates as described below). Implement your methods in as exception-safe a manner as "reasonably" feasible.

Complete the demonstration program, and add a Makefile that builds it, so that you can test-compile your code. The demonstration program does not need to fully exercise the class, but it should "demonstrate" all the methods you wrote. This is important. The compiler will not instantiate a method that is not used. Certain compilation errors in your work could be masked until your demonstration program actually calls all the methods.

Note that you can exercise the move constructor by returning a matrix from a function and use the return value as the initializer for another Matrix (the compiler will move-construct the new Matrix from the return value). You can exercise the move assignment operator using std::move:

  Matrix<double> m1(10, 10);
  Matrix<double> m2(10, 10);
  // ...
  m1 = std::move(m2);

You may find my tutorial on matrix math useful if you are unfamiliar with how matrix operations are done. Note also that accessing the matrix elements makes use of an overloaded operator() rather than using an overloaded operator[] as you might expect. For more information about why this was done, see this FAQ.

In a manner similar to BigInteger, class Matrix is intended to hold a pointer to a dynamically allocated array of floating point values containing the data in the matrix. Copying and assigning Matrix objects should copy this array as needed using the life cycle methods.

To be as general as possible, Matrix should be a template that allows any of the three standard floating point types to be used with it. Clients should be able to declare Matrix<float>, Matrix<double>, and Matrix<long double> objects. Think about if your implementation could be instantiated with BigInteger as the element type.

C++ requires that the bodies of all templates be in header files where they can be seen by the compiler when client code is processed. For this reason, you do not need to create a .cpp file for this assignment.

IMPORTANT!

For this assignment you should dynamically allocate a block of floating point values and access that block via a pointer stored in the private section of your Matrix class. Another approach, which is easier, is to implement Matrix using a vector of vectors. That approach means that Matrix resource management would be done automatically by the vector class.
However, the point of this assignment is for you to learn about how that resource management is done! Therefore, you should use the lower-level approach for this assignment.

Part 2: Extra Credit (up to 5 points)

Normally, inside a const method of a class, the data members (fields) of the class are treated as constants. That way, any attempt made by the const method to modify a data member will result in a compile-time error. However, when a class contains members that are pointers, a loophole is created in the protection offered by const. Explain. For example, in what way could a const method of the Matrix class effectively modify the value of a constant Matrix without the compiler complaining? (HINT: there is a difference between a "constant pointer" and a "pointer to a constant.") Do you think this is a problem? (This last question is open-ended; just say something reasonable.)

Submit your modified Matrix.hpp, your Makefile, your updated demonstration program, and your answer to the extra credit question (if you choose to do it) in a single zip archive to Canvas.


Last Revised: 2023-09-27
© Copyright 2023 by Peter Chapin <peter.chapin@vermontstate.edu>