一、头文件创建
1.头文件定义了CMatrix类、类內部属性、函数、以及各种调用方法
头文件定义格式如下,属于条件编译宏定义,可以根据条件选择性的只编译某段程序,也可以防止重复定义。
#ifndef CMATRIX_H #define CMATRIX_H // 具体的 // 头文件 // 正文内容 #endif
二、有几类函数:
1.构造函数
①不带参数的构造函数;// CMatrix();
②带行、列及数据指针等参数的构造函数,并且参数带默认值;//CMatrix(int nRow, int nCol, double *pData=NULL) ;
③带文件路径参数的构造函数;//CMatrix(const char * strPath);
④ 拷贝构造函数 //CMatrix(const CMatrix& m);
⑤此外会用列表初始化成员变量:CMatrix(): m_nRow(0), m_nCol(0), m_pData(NULL);
bool Create(int nRow, int nCol, double *pData=NULL): 先删除原有空间,根据传入行列创建空间,如果pData不为空要将pData的内容拷贝到m_pData中。
CMatrix的一个重载函数:当m_pData的空间不能容纳n_Row*n_Col时 m_pData=NULL
▲特点:
构造函数具有如下几个特点:
①名字与类名相同,可以有参数,但是不能有返回值(void也不行);
②作用是对对象进行初始化工作,如给成员变量赋值等;
③如果定义类时没有写构造函数,系统会生成一个默认的无参构造函数,默认构造函数没有参数,不做任何工作;
④如果定义了构造函数,系统不再生成默认的无参构造函数;
⑤对象生成时构造函数自动调用,对象一旦生成,不能在其上再次执行构造函数
一个类可以有多个构造函数,为重载关系。
其中:构造函数CMatrix的初始化有两种方式:
①在给变量分配空间时就直接赋值即可,这种方法初始化效率较高
②在分配空间之后再给变量赋值
值得注意的是,初始化时,变量的顺序必须和定义时变量的顺序一致
▲用法:
CMatrix::CMatrix()
{
m_nRow = 0;
m_nCol = 0;
m_pData = NULL;
}
// 注意:传入参数的顺序和在类间定义时顺序一致
CMatrix::CMatrix():m_nRow(0), m_nCol(0), m_pData(0)
{
// 初始化为NULL
}
// 有参构造函数
CMatrix::CMatrix(int nRow, int nCol, double *pData):m_pData(0)
{
Create(nRow,nCol,pData); //调用创建对象的方法
}
// 拷贝构造函数
CMatrix::CMatrix(const CMatrix& m):m_pData(0)
{
*this = m; // 因为这里的*this表示对象指针,赋值的是地址
}
// 对str对象操作
CMatrix::CMatrix(const char * strPath)
{
m_pData = 0;
m_nRow = m_nCol = 0;
ifstream cin(strPath); // 文件操作
cin >> *this;
}
2. 析构函数
①调用Release(); // ~CMatrix():
②将内存释放,并将行列设置为0;//Release():
▲特点:
①析构函数名应与类名相同,只是在函数名前面加一个位取反符,以区别于构造函数。
②它不能带任何参数,也没有返回值(包括void类型)。由于没有函数参数,因此它不能被重载,只能有一个析构函数。
③如果用户没有编写析构函数,编译系统会自动生成一个缺省的析构函数(即使自定义了析构函数,编译器也总是会为我们合成一个析构函数,并且如果自定义了析构函数,编译器在执行时会先调用自定义的析构函数再调用合成的析构函数),它也不进行任何操作。所以许多简单的类中没有用显示的析构函数。
④当对象的生命周期结束时,撤销类对象时候会自动调用析构函数。
⑤对象在生命期结束,撤销类对象时会自动调用析构函数。
⑥如果用new运算动态地建立一个对象,那用delete运算符释放该对象时,才会调用析构函数。
▲用法:
// 析构函数,用于释放
CMatrix::~CMatrix()
{
Release();
}
3.运算符重载
①算术运算符重载:+, -, +=, -=
②关系运算符重载:>, <, ==
③下标操作符:[], ()
④强制类型转换: double
⑤赋值运算符:=,尤其注意当m1=m1特殊情况的处理
▲用法:
CMatrix& operator=(const CMatrix& m); CMatrix& operator+=(const CMatrix& m); double& operator[](int nIndex); double& operator()(int nRow, int nCol); bool operator ==(const CMatrix& m); bool operator !=(const CMatrix& m);
△运算符重载
// "="重载
CMatrix& CMatrix::operator = (const CMatrix& m)
{
if(this!=&m)
{
Create(m.m_nRow, m.m_nCol, m.m_pData);
}
return *this;
}
// "=="重载
bool CMatrix::operator == (const CMatrix& m)
{
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;
}
// "!="重载
bool CMatrix::operator != (const CMatrix& m){
return !((*this)==m);
}
// "+="重载
CMatrix& CMatrix::operator += (const CMatrix& m)
{
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;
}
// "+"重载
CMatrix operator + (const CMatrix& m1, const CMatrix& m2)
{
CMatrix m3(m1);
m3 += m2;
return m3;
}
// "-="重载
CMatrix& CMatrix::operator -= (const CMatrix& m)
{
assert(m_nRow==m.m_nRow && m_nCol==m.m_nCol);
for (int i=0;i
△操作符重载
// "[]"重载
double & CMatrix::operator[](int nIndex)
{
//判定下标越界
assert(nIndex>"重载
istream & operator>>(istream& is, CMatrix & m)
{
is>>m.m_nRow>>m.m_nCol;
// 初始化
m.Create(m.m_nRow, m.m_nCol);
// 逐行赋值
for(int i=0;i>m.m_pData[i];
}
return is;
}
// "<<"重载
ostream & operator<<(ostream& os, const CMatrix &m)
{
os<<"size:["<
4.友元函数
输入和输出运输符:<<, >>
friend istream& operator>>(istream& is, CMatrix& m);
friend ostream& operator<<(ostream& os, const CMatrix& m);
①赋予特权,特殊声明,friend加了之后为全局函数不是成员函数,类里面定义的所有对象都可以调用,所以可以访问下面的private私有变量;
②输出输入流运算符重载,原本输出输入流只能针对基础的数据类型,比如char,int,double,指针,重载后使其能够读取自己定义的类。
5.主函数
#include
#include
#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("./1.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 << "sum of m4 = " << (double)m4 << endl;
return 0;
}
三、正文内容如下:
#ifndef CMATRIX_H
#define CMATRIX_H
#include
using namespace std;
class CMatrix
{
private: //二维矩阵类变量定义
int m_nRow;//行数
int m_nCol;//列数
double * m_pData=NULL;//用于存储矩阵中所有值地址的指针,初始化为NULL
public:
CMatrix(); //构造器
//如果nRow=0有默认值则之后的都得有默认值
//若都默认值为0,相当于无参数,则会与上一个构造函数CMatrix();产生歧义,不知道调用哪一个
//带行、列及数据指针等参数的构造函数, 并且参数带默认值
CMatrix(int nRow, int nCol, double * pDate = NULL); //拷贝构造函数
CMatrix(const CMatrix& m); //带文件路径参数的构造函数
CMatrix(const char * strPah);
~CMatrix(); //析构函数
bool Create(int nRow, int nCol, double* pDate); //初始化
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);
double & operator[](int nIndex);
double & operator()(int nRow,int nCol);
bool operator == (const CMatrix& m);
bool operator != (const CMatrix& m);
//重载类型转换
operator double();
};
// 重载运算符 "+"
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


![[C++实验1]CMatrix类设计与实现 [C++实验1]CMatrix类设计与实现](http://www.mshxw.com/aiimages/31/395847.png)
