实验一
一、构造函数
1.CMatrix(): 不带参数的构造函数;
//CMatrix::CMatrix(){
// m_nRow=m_nCol=0;
// m_pData=0;
//}
//好处:申请出m_nRow,m_nCol,m_pData的空间的时候顺便初始化
CMatrix::CMatrix():m_nRow(0),m_nCol(0),m_pData(0)
{
}
2.CMatrix(int nRow, int nCol, double *pData=NULL) : 带行、列及数据指针等参数的构造函数,并且参数带默认值;
// CMatrix::CMatrix(int nRow,int nCol,double *pData):m_pData(0)
// {
// Create(nRow,nCol,pData);
// }
// 带行, 列 及数据指针 等参数的 构造函数, 并 且参数带默认值
CMatrix::CMatrix(int nRow,int nCol,double *pData){
m_pData=NULL;
Create(nRow,nCol,pData);
}
3.CMatrix(const char * strPath): 带文件路径参数的构造函数;
//带文件路径参数的构造函数
CMatrix::CMatrix(const char * strPath)
{
// m_pData = 0; //不置为0,随机数
// m_nRow = m_nCol = 0;
ifstream is(strPath);
is>>*this; //this本身地址的指针
}
4.CMatrix(const CMatrix& m): 拷贝构造函数
CMatrix::CMatrix(const CMatrix &m):CMatrix(m.m_nRow,m.m_nCol,m.m_pData){
// m_nRow=m.m_nRow;
// m_nCol=m.m_nCol;
// m_pData=NULL;
// Create(m_nRow,m_nCol,m.m_pData);
}
5.bool Create(int nRow, int nCol, double *pData=NULL): 先删除原有空间,根据传入行列创建空间,如果pData不为空要将pData的内容拷贝到m_pData中。
//先删除原有空间,根据传入行列创建空间,如果pData 不为空要将pData的内容拷贝到m_pData
bool CMatrix::Create(int nRow,int nCol,double *pData)
{
Release();
//新建一个空间来存储数据
m_pData = new double[nRow*nCol];
m_nRow = nRow;
m_nCol = nCol;
if(m_pData!=NULL){
if(pData!=NULL)
{
memcpy(m_pData,pData,nRow*nCol*sizeof(double));
}
return true;
}
else{
return false;
}
}
二、析构函数
1.~CMatrix(): 调用Release();
析构函数:当对象结束其生命周期,如对象所在的函数已调用完毕时,系统自动执行析构函数。析构函数往往用来做“清理善后” 的工作
// 析构函数, 调用函数 Release,将内存 释放,并 将行 列设置为0
CMatrix::~CMatrix()
{
Release();
}
2.Release(): 将内存释放,并将行列设置为0;
void CMatrix::Release(){
if(m_pData!=NULL){
delete []m_pData; //删除之后
m_pData=NULL; //赋值为空
}
m_nRow=m_nCol=0;
}
三、运算符重载
运算符重载:重载的运算符是带有特殊名称的函数,函数名是由关键字 operator 和其后要重载的运算符符号构成的。与其他函数一样,重载运算符有一个返回类型和一个参数列表。
1.算术运算符重载:+, -, +=, -=
CMatrix operator+(const CMatrix& m1,const CMatrix& m2)
{
CMatrix m3(m1);
m3 += m2;
return m3;
}
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<m_nRow*m_nCol;i++)
{
m_pData[i]+=m.m_pData[i];
} return *this;
}
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;
}
2.关系运算符重载:>, <, ==
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;
}
3.下标操作符:[], ()
double & CMatrix::operator[](int nIndex)
{
assert(nIndex<m_nRow*m_nCol);
return m_pData[nIndex];
}
double & CMatrix::operator()(int nRow,int nCol) {
assert(nRow*m_nCol+nCol<m_nRow*m_nCol);
return m_pData[nRow*m_nCol+nCol];
}
4.强制类型转换: double
CMatrix::operator double()
{
double dS=0;
for(int i=0;i<m_nRow*m_nCol;i++)
{
dS+=m_pData[i];
}
return dS;
}
5.赋值运算符:=,尤其注意当m1=m1特殊情况的处理
CMatrix& CMatrix::operator=(const CMatrix& m)
{
if(this!=&m){
Create(m.m_nRow,m.m_nCol,m.m_pData);
}
return *this;
}
四、友元函数
友元函数是指某些虽然不是类成员却能够访问类的所有成员的函数。类授予它的友元特别的访问权。通常同一个开发者会出于技术和非技术的原因,控制类的友元和成员函数
1.输入和输出运输符:<<, >>
//运算符重载,从流中读入
istream & operator>>(istream& is,CMatrix & m) {
// m.Release(); //释放
is>>m.m_nRow>>m.m_nCol; //访问公有变量,私有变量是访问不到的
m.Create(m.m_nRow,m.m_nCol); //创建函数有Release可以省略
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)
{
os<<m.m_nRow<<" "<<m.m_nCol<<endl;
double * pData = m.m_pData;
for(int i=0;i<m.m_nRow;i++)
{
for(int j=0;j<m.m_nCol;j++)
{
os<<*pData++<<" ";
}
os<<endl; //"\n"
}
return os;
}
五、总结
初步认识构造函数,构造函数(带文件路径的,带指针参数等),析构函数,运算符重载,友元函数。
还有其他编写程序的方法,比如
CMatrix::CMatrix(){
m_nRow=m_nCol=0;
m_pData=0;
}
//好处:申请出m_nRow,m_nCol,m_pData的空间的时候顺便初始化
CMatrix::CMatrix():m_nRow(0),m_nCol(0),m_pData(0)
{
}
上下两种写法相同,但是下面能使空间初始化,省掉了一些步骤