C++. An example of creating a template class Matrix. Dynamic memory allocation




An example of creating a template class MATRIX. Dynamic memory allocation

The example demonstrates the creation of the MATRIX template class. The class implements a matrix of size m×n. The memory for the matrix is allocated dynamically.

In this example, you can create and use your own classes that contain data structures in which memory is allocated dynamically.

In the class implemented:

  • hidden (private) internal variable M of type “pointer to pointer”. This variable determines the matrix. The memory for the matrix will be allocated dynamically;
  • two integer internal private variables m, n. These variables define the dimension of the matrix M;
  • default constructor;
  • constructor with two parameters MATRIX (int, int). This constructor creates a matrix o m×n size. The constructor allocates memory for the columns and rows of the matrix. The value of each matrix element is set to 0;
  • copy constructor MATRIX(MATRIX&). This constructor is needed to create a copy of the matrix object from another matrix object;
  • methods for reading/writing matrix elements GetMij(), SetMij();
  • the Print() method, which displays the matrix;
  • copy operator operator=(MATRIX&). This operator overloads the assignment operator = and is intended for the correct copying of objects of type obj2 = obj1;
  • destructor.

The class implementation for an application of the Console Application type is as follows

#include <iostream>
using namespace std;

// template class Matrix
template <typename T>
class MATRIX
{
private:
  T** M; // matrix
  int m; // number of rows
  int n; // number of columns

public:
  // constructors
  MATRIX()
  {
    n = m = 0;
    M = nullptr; // not necessary
  }

  // constructor with two parameters
  MATRIX(int _m, int _n)
  {
    m = _m;
    n = _n;

    // Allocate memory for matrix
    // Allocate memory for pointer array
    M = (T**) new T*[m]; // number of rows, the number of pointers

    // Allocate memory for each pointer
    for (int i = 0; i < m; i++)
      M[i] = (T*)new T[n];

    // fill array M with zeros
    for (int i = 0; i < m; i++)
      for (int j = 0; j < n; j++)
        M[i][j] = 0;
  }

  // copy constructor - mandatory
  MATRIX(const MATRIX& _M)
  {
    // A new object is created for which memory is allocated.
    // Copy data *this <= _M
    m = _M.m;
    n = _M.n;

    // Allocate memory for M
    M = (T**) new T*[m]; // number rows, number pointers

    for (int i = 0; i < m; i++)
      M[i] = (T*) new T[n];

    // fill with values
    for (int i = 0; i < m; i++)
      for (int j = 0; j < n; j++)
        M[i][j] = _M.M[i][j];
  }

  // access methods
  T GetMij(int i, int j)
  {
    if ((m > 0) && (n > 0))
      return M[i][j];
    else
      return 0;
  }

  void SetMij(int i, int j, T value)
  {
    if ((i < 0) || (i >= m))
      return;
    if ((j < 0) || (j >= n))
      return;
    M[i][j] = value;
  }

  // a method that displays a matrix
  void Print(const char* ObjName)
  {
    cout << "Object: " << ObjName << endl;
    for (int i = 0; i < m; i++)
    {
      for (int j = 0; j < n; j++)
        cout << M[i][j] << "\t";
      cout << endl;
    }
    cout << "---------------------" << endl << endl;
  }

  // copy operator - mandatory
  MATRIX operator=(const MATRIX& _M)
  {
    if (n > 0)
    {
      // free memory previously allocated for the object *this
      for (int i = 0; i < m; i++)
        delete[] M[i];
    }

    if (m > 0)
    {
      delete[] M;
    }

    // Copy data M <= _M
    m = _M.m;
    n = _M.n;

    // Allocate memory for M again
    M = (T**) new T*[m]; // number of rows, number of pointers

    for (int i = 0; i < m; i++)
      M[i] = (T*) new T[n];

    // fill with values
    for (int i = 0; i < m; i++)
      for (int j = 0; j < n; j++)
        M[i][j] = _M.M[i][j];
    return *this;
  }

  // Destructor - frees memory allocated for the matrix
  ~MATRIX()
  {
    if (n > 0)
    {
      // release the memory allocated for each row
      for (int i = 0; i < m; i++)
        delete[] M[i];
    }

    if (m > 0)
      delete[] M;
  }
};

void main()
{
  // test for class MATRIX
  MATRIX<int> M(2, 3);
  M.Print("M");

  // Fill the matrix with values according to the formula
  int i, j;
  for (i = 0; i < 2; i++)
    for (j = 0; j < 3; j++)
      M.SetMij(i, j, i + j);
  M.Print("M");

  MATRIX<int> M2 = M; // invoke the copy constructor
  M2.Print("M2");

  MATRIX<int> M3; // invoke the copy operator - checking
  M3 = M;
  M3.Print("M3");

  MATRIX<int> M4;
  M4 = M3 = M2 = M; // invoke the copy operator as a chain
  M4.Print("M4");
}





The result of the program

Object: M
0       0       0
0       0       0
---------------------

Object: M
0       1       2
1       2       3
---------------------

Object: M2
0       1       2
1       2       3
---------------------

Object: M3
0       1       2
1       2       3
---------------------

Object: M4
0       1       2
1       2       3
---------------------

Total. If the memory in the class is allocated dynamically, then you must definitely implement your own copy constructor and copy operator.

 


Related topics