初识C++:CMatrix类的实现
1.头文件声明 Cmatrix.h
头文件主要用于声明CMatrix 类以及类内部的属性和构造函数,和各种实现方法。
#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 Release();
void Set(int nRow, int nCol, double dVale);
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);
bool operator ==(const CMatrix& m);
bool operator !=(const CMatrix& m);
double & operator[](int nIndex);
double & operator()(int nRow, int nCol);
operator double();
private:
int m_nRow;
int m_nCol;
double *m_pData = NULL;
};
CMatrix operator+(const CMatrix& m1, const CMatrix& m2);
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
其中,这三行代码属于条件编译宏定义,可以根据条件选择性的只编译某段程序,也可以防止重复定义。
#ifndef CMATRIX_H
#define CMATRIX_H
#endif
2.类内部方法,函数的实现 CMatrix.cpp
2.1构造器(Constructor)
构造器最大的用处就是在创建对象时执行初始化,当创建一个对象时,系统会为这个对象的实例进行默认的初始化。如果想改变这种默认的初始化,就可以通过自定义构造器来实现。 由于c++面向对象语言的特性,构造器可以实现重载,即一个类可以有多个构造器。一个类的构造器的名称必须与该类的名称一致。
2.1.1 缺省构造器
CMatrix::CMatrix()
{
m_nRow = 0;
m_nCol = 0;
m_pData = NULL;
}
无参构造器(使用初始化表达式):
CMatrix::CMatrix():m_nRow(0),m_nCol(0),m_pData(0)
{
}
2.1.2 有参构造器
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;
}
外部数据流构造函数
CMatrix::CMatrix(const char * strPath):m_nRow(0),m_nCol(0),m_pData(0)
{
ifstream cin(strPath);
cin>>*this;
}
2.2析构函数(Destructor)
析构函数与构造函数相反,当对象结束其生命周期,如对象所在的函数已调用完毕时,系统自动执行析构函数。析构函数往往用来做“清理善后” 的工作(例如在建立对象时用new开辟了一片内存空间,delete会自动调用析构函数后释放内存)。
CMatrix::~CMatrix()
{
Release();
}
2.3 CMatrix 对象方法
2.3.1对象初始化
bool CMatrix::Create(int nRow, int nCol, double *pData)
{
Release();
m_pData = new double[nRow*nCol];
m_nRow = nRow;
m_nCol = nCol;
if(pData != NULL)
{
memcpy(m_pData, pData, nRow*nCol*sizeof(double));
}
}
2.3.2 对象销毁方法
void CMatrix::Release()
{
if(m_pData != NULL)
{
delete []m_pData;
m_pData = NULL;
}
m_nRow = m_nCol = 0;
}
2.4 CMatrix 运算符重载
在c++中,可以重定义或重载大部分内置的运算符。这样就可以使用自定义类型的运算符,实现更为复杂的运算。
重载的运算符是带有特殊名称的函数,函数名是由关键字 operator 和其后要重载的运算符符号构成的。与其他函数一样,重载运算符有一个返回类型和一个参数列表。
2.4.1 赋值运算符重载
CMatrix& CMatrix::operator=(const CMatrix& m)
{
if(this!=&m){
Create(m.m_nRow, m.m_nCol, m.m_pData);
}
return *this;
}
2.4.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;
}
“!=“运算符重载
bool CMatrix::operator !=(const CMatrix& m){
return !((*this)==m);
}
2.4.3运算符重载
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;
}
"+"重载
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;
}
2.4.4 操作符重载
下标操作符[]重载
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];
}
操作符”>>“重载
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_nRow*m.m_nCol;i++)
{
is>>m.m_pData[i];
}
return is;
}
操作符”<<“重载
ostream & operator<<(ostream& os, const CMatrix &m)
{
os<<"size:["<<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;
}
return os;
}
重载强制类型转换
CMatrix::operator double()
{
double dS=0;
for(int i=0;i<m_nRow*m_nCol;i++){
dS+=m_pData[i];
}
return dS;
}
3.主函数测试样例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("../1.txt"), m4(m2);
cin>>m1;
m2.Set(1,3,10);
m4=m3;
m4[2] = m4 + 1;
cout<<m1<<m2<<m3<<m4;
if(m4 == m3)
{
cout<<"Error !"<<endl;
}
m4 -= m3;
cout<<"m4 -= m3:\n"<<m4;
cout<<"m4 -= m3 = "<<(double)m4<<endl;
return 0;
}
运行结果:
pi@raspberrypi:~/Desktop/cpp/build $ ./main
2 2
4 4 4 4
size:[2,2]
4 4
4 4
size:[2,5]
2 3 4 5 0
0 0 0 10 0
size:[2,2]
1 2
3 4
size:[2,2]
1 2
11 4
m4 -= m3:
size:[2,2]
0 0
8 0
m4 -= m3 = 8
pi@raspberrypi:~/Desktop/cpp/build $
值得注意的是,在执行m4 + 1(或者1 + m4)运算的过程中,程序会默认先将m4解析为(double)m4,然后再加1。(这里先留一个小疑问)
还有就是对于双目运算符"+" , "-"的重载,必须定义在类的外部,否则编译过程中会报错。
|