Design and implementation of CMatrix class (the first experiment of C + +)

Keywords: C++

1. Constructor:

1.1 concept of constructor

Compared with C language, C + + has a better feature is constructor, that is, a class controls the initialization process of its object through one or several special member functions. The task of the constructor is to initialize the data members of the object. Whenever the object of the class is created, the constructor will be executed.

1.2 CMatrix(): constructor without parameters

code:

 CMatrix::CMatrix() : m_nRow(0), m_nCol(0), m_pData(0)  //non-parameter constructor  
 {
	
 }

Note that CMatrix:: CMatrix(): M_ nRow(0), m_ nCol(0), m_ Pdata (0) and CMatrix (){
m_nRow=0,m_nCol=0,m_pData=0} have the same effect, but the construction speed of the former is faster.

1.3 CMatrix(int nRow, int nCol, double *pData=NULL): constructor with parameters such as row, column and data pointer, and parameters with default values

code:

 CMatrix::CMatrix(int nRow, int nCol, double* pData) : m_pData(0) // Constructor with three arguments 
 {
	     Create(nRow, nCol, pData);  //Call the new class object method
 }

1.4 CMatrix(const char * strPath): constructor with file path parameter

 CMatrix::CMatrix(const char* strPath)
 {
	     m_pData = 0;
	     m_nRow = m_nCol = 0;
	     ifstream cin(strPath);
	     cin >> *this;
 }

be careful:
ofstream: file class of write operation (output) (derived from ostream)
ifstream: file class of read operation (input) (derived from istream)
Fsstream: a file class that can read and write at the same time (derived from iostream)
ofstream is from memory to hard disk, and ifstream is from hard disk to memory. In fact, the so-called stream buffer is memory space

1.5 CMatrix (const CMatrix & M): copy constructor

code:

 CMatrix::CMatrix(const CMatrix & m) : m_pData(0) //Constructor with a parameter object 
 {
	     *this = m;
 }

What is a copy build function?
Copy constructor is a kind of constructor, also known as copy constructor. It has only one parameter, and the parameter type is the reference of this class.
The parameters of the copy constructor can be const references or non const references.
The former is generally used. In this way, both constant objects (objects whose values cannot be changed after initialization) and non constant objects can be used as parameters to initialize other objects. It is also possible to write two copy constructors in a class. One parameter is const reference and the other parameter is non const reference.

2. Destructor

concept

destructor is a kind of member function. Its name is the same as the class name, but it should be preceded by ~. It has no parameters and return value.

A class has only one destructor. If the destructor is not written when the class is defined, the compiler generates a default destructor. If a destructor is defined, the compiler does not generate a default destructor.

Destructors are called automatically when an object dies. You can define destructors to do aftercare before the object dies.

2.1 ~CMatrix(): call Release();

 CMatrix::~CMatrix()
 {
	     Release();
 }
 

3. CMatrix object method

3.1 object initialization: bool CMatrix::Create(int nRow, int nCol, double* pData)

 bool CMatrix::Create(int nRow, int nCol, double* pData)
 {
	     Release();
	     m_pData = new double[nRow * nCol];
	     m_nRow = nRow;
	     m_nCol = nCol;
	     if (pData)
		 {
		         memcpy(m_pData, pData, nRow * nCol * sizeof(double));  
		         //memcpy memory copy function, copy nRow * nCol * sizeof(double) bytes from pData to M_ In pData 
		 }
 }

3.2 object destruction: Release()

void CMatrix::Release()
 {
	     if (m_pData)
		 {
		         delete[]m_pData;  //Memory release
		         m_pData = NULL;
		  }
	 m_nRow = m_nCol = 0;   //Set row and column to 0
 }

The object destruction function Release() actually releases the memory and sets the row and column to 0.

4. Operator overloading

4.1 arithmetic operator overloading: +, -, + =-=

code:

CMatrix & CMatrix::operator+=(const CMatrix & m)   //+=Operator overloading
 {
	   assert(m_nRow == m.m_nRow && m_nCol == m.m_nCol);
	  //assert assertion function to judge the assumptions in parentheses. If it does not meet the conditions, it will throw an error and terminate the program
	   for (int i = 0; i < m_nRow * m_nCol; i++)
	 {
		  m_pData[i] += m.m_pData[i];
	 }
	   return *this;
 }
CMatrix operator+(const CMatrix & m1, const CMatrix & m2)  //+Operator overloading
{
		    CMatrix m3(m1);
		    m3 += m2;
		    return m3;
 }
 CMatrix operator-(const CMatrix& m1, const CMatrix& m2)   //-Operator overloading 
{
		CMatrix m3(m1);
		m3 -= m2;
		return m3;
}
CMatrix& CMatrix::operator-=(const CMatrix& m)  //-=Operator overloading 
{
		//assert assertion function to judge the assumptions in parentheses. If it does not meet the conditions, it will throw an error and terminate the program
		assert(m_nRow == m.m_nRow && m_nCol == m.m_nCol);
		for (int i = 0; i < m_nRow * m_nCol; i++)
		{
			m_pData[i] -= m.m_pData[i];
		}
		return *this;
}

4.2 overloading of relational operators: >, <==

code:

bool CMatrix::operator == (const CMatrix & m)  //==Overloading of operators
 {
	     if (!(m_nRow == m.m_nRow && m_nCol == m.m_nCol))
		 {
		         return false;
		  }
	 for (int i = 0; i < m_nRow * m_nCol; i++)
		 {
		         if (m_pData[i] != m.m_pData[i])
			 {
			             return false;
			 }
		 }
	     return true;
 }
 

4.3 overloading of subscript operators [], ()

code:

double& CMatrix::operator[](int nIndex)  //Overloading of [] operator
 {
	     assert(nIndex < m_nRow * m_nCol);
	     return m_pData[nIndex];
 }
 double& CMatrix::operator()(int nRow, int nCol) //Overload of () operator
 {
	     assert(nRow * m_nCol + nCol < m_nRow * m_nCol);
	     return m_pData[nRow * m_nCol + nCol];
 }

4.4 forced type conversion: double

code:

CMatrix::operator double()  //Overload cast
{
	double dS = 0;
	for (int i = 0; i < m_nRow * m_nCol; i++)
	{
		dS += m_pData[i];
	}
	return dS;
}

4.5 assignment operator:=

code:

CMatrix& CMatrix::operator=(const CMatrix& m)   //=Overloading of operators
{
	if (this != &m)
	{
		//The "=" assignment adopts the Create method, which is a deep copy
		Create(m.m_nRow, m.m_nCol, m.m_pData);
	}
	return *this;
}

5. Friend function

5.1 input and output transportation symbols: <, > >

code:

 istream & operator>>(istream& is, CMatrix& m) //>>Overloaded operation of operator
 {
	     is >> m.m_nRow >> m.m_nCol; //Initialize before reading the matrix
	     m.Create(m.m_nRow, m.m_nCol);
	     for (int i = 0; i < m.m_nRow * m.m_nCol; i++)
		 {
		         is >> m.m_pData[i];
		 }
	 return is;
 }
 ostream & operator<<(ostream & os, const CMatrix & m) //< < overloaded operation of operator
 {
	     os << m.m_nRow << " " << m.m_nCol << endl;
	     double* pData = m.m_pData; //Output matrix elements in row column order
	     for (int i = 0; i < m.m_nRow; i++)
		 {
		         for (int j = 0; j < m.m_nCol; j++)
				 {
			             os << *pData++ << " ";
				  }
		 os << endl;
		 }
	     return os;
}

6. The main function main.cpp and the header file CMatrix.h

main.cpp:

#include <iostream>
#include <stdio.h>
#include "CMatrix.h"
 using namespace std;
 int main(int argc, char** argv) {
    
     double pData[10]={2,3,4,5};
     CMatrix m1,m2(2,5,pData), m3("C:\\Users\\Administrator\\Desktop\\C++\\First experiment\\Test text.txt"),m4(m2);
     cin>>m1;
     m2.Set(1,3,10);
     cout<<m1<<m2<<m3<<m4;
     m4=m3;
     m4[2]=m4+1;
     if(m4==m3)
     {
         cout<<"Error !"<<endl;
     }
     m4 += m3;
     cout<<"m4 Sum of = "<<(double)m4<<endl;
     return 0;
 }

CMatrix.h:

#ifndef CMATRIX_H
#define CMATRIX_H
#include <iostream>
 using namespace std;
 class CMatrix
 {
     public:
         CMatrix();
             CMatrix(int nRow, int nCol, double* pData = NULL);
             CMatrix(const CMatrix & m);
             CMatrix(const char* strPath);
             ~CMatrix();
             bool Create(int nRow, int nCol, double* pData = NULL);
             void Set(int nRow, int nCol, double dVale);
             void Release();
             friend istream & operator>>(istream& is, CMatrix& m);
             friend ostream & operator<<(ostream & os, const CMatrix & m);
        
         CMatrix & operator=(const CMatrix & m);
             CMatrix & operator+=(const CMatrix & m);
         //  CMatrix& operator+(const CMatrix& m);
         //  CMatrix operator+(const CMatrix& m1,const CMatrix& m2);
             double& operator[](int nIndex);
             double& operator()(int nRow, int nCol);
             bool operator ==(const CMatrix & m);
             bool operator !=(const CMatrix & m);
        
         operator double();
        
         private:
             int m_nRow;
                 int m_nCol;
                double* m_pData;
};
 CMatrix operator+(const CMatrix & m1, const CMatrix & m2);
 inline void CMatrix::Set(int nRow, int nCol, double dVal)
 {
         m_pData[nRow * m_nCol + nCol] = dVal;
 }
  #endif

7. Experimental results and summary


Copy constructor is a kind of constructor, also known as copy constructor. It has only one parameter, and the parameter type is the reference of this class.
The parameters of the copy constructor can be const references or non const references.
The former is generally used. In this way, both constant objects (objects whose values cannot be changed after initialization) and non constant objects can be used as parameters to initialize other objects. It is also possible to write two copy constructors in a class. One parameter is const reference and the other parameter is non const reference.

destructor is a kind of member function. Its name is the same as the class name, but it should be preceded by ~. It has no parameters and return value.
A class has only one destructor. If the destructor is not written when the class is defined, the compiler generates a default destructor. If a destructor is defined, the compiler does not generate a default destructor.
Destructors are called automatically when an object dies. You can define destructors to do aftercare before the object dies.

ofstream: file class of write operation (output) (derived from ostream)
ifstream: file class of read operation (input) (derived from istream)
Fsstream: a file class that can read and write at the same time (derived from iostream)
ofstream is from memory to hard disk, and ifstream is from hard disk to memory. In fact, the so-called stream buffer is memory space

Posted by cristal777 on Tue, 12 Oct 2021 11:20:05 -0700