实验内容
一、构造函数
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(): 调用Release();
Release(): 将内存释放,并将行列设置为0;
三、运算符重载
Ø算术运算符重载:+, -, +=, -=
Ø关系运算符重载:>, <, ==
Ø下标操作符:[], ()
Ø强制类型转换: double
Ø赋值运算符:=,尤其注意当m1=m1特殊情况的处理
四、友元函数
输入和输出运输符:<<, >>
实验代码
1.项目结构
2.源码
CComplex.h
#ifndef CCOMPLEX_H
#define CCOMPLEX_H
#include <iostream>
using namespace std;
struct SComplex
{
double m_dReal;
double m_dImag;
};
double Modulus(const SComplex & sc);
void Output(const SComplex & sc);
void Input(SComplex & sc);
class CComplex
{
public:
double m_dReal;
double m_dImag;
double Modulus();
void Output();
void Input();
};
istream& operator>>(istream& is, CComplex& cc);
ostream& operator<<(ostream& os, const CComplex& cc);
#endif
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);
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
CComplex.cpp
#include "CComplex.h"
#include <math.h>
#include <stdio.h>
double Modulus(const SComplex & sc)
{
return sqrt(sc.m_dReal*sc.m_dReal+sc.m_dImag*sc.m_dImag);
}
void Output(const SComplex & sc)
{
printf("%f%f\n",sc.m_dReal,sc.m_dImag);
}
void Input(SComplex & sc)
{
scanf("%lf%lf",&sc.m_dReal,&sc.m_dImag);
}
double CComplex::Modulus()
{
return sqrt(m_dReal*m_dReal+m_dImag*m_dImag);
}
void CComplex::Output()
{
printf("%f %f\n",m_dReal,m_dImag);
}
void CComplex::Input()
{
scanf("%lf%lf",&m_dReal,&m_dImag);
}
istream& operator>>(istream& is, CComplex& cc)
{
is>>cc.m_dReal>>cc.m_dImag;
return is;
}
ostream& operator<<(ostream& cout, const CComplex& cc)
{
cout<<cc.m_dReal<<" "<<cc.m_dImag<<endl;
return cout;
}
CMatrix.cpp
#include "CMatrix.h"
#include <fstream>
#include <assert.h>
CMatrix::CMatrix():m_nRow(0),m_nCol(0),m_pData(0)
{
}
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_pData = 0;
m_nRow = m_nCol = 0;
ifstream cin(strPath);
cin>>*this;
}
CMatrix::~CMatrix()
{
Release();
}
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));
}
}
void CMatrix::Release()
{
if(m_pData)
{
delete []m_pData;
m_pData = NULL;
}
m_nRow = m_nCol = 0;
}
CMatrix& CMatrix::operator=(const CMatrix& m)
{
if(this!=&m){
Create(m.m_nRow,m.m_nCol,m.m_pData);
}
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;
}
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];
}
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::operator double()
{
double dS=0;
for(int i=0;i<m_nRow*m_nCol;i++)
{
dS+=m_pData[i];
}
return dS;
}
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<<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;
}
main.cpp
#include <iostream>
#include "CComplex.h"
#include <stdio.h>
#include "CMatrix.h"
#include<string.h>
using namespace std;
int main(int argc, char** argv) {
double pData[10]={2,3,4,5};
CMatrix m1,m2(2,4,pData), m3("D:\\pang.txt"),m4(m2);
cin>>m1;
m2.Set(1,1,7);
cout<<"\nm1:\n"<<m1<<"\nm2:\n"<<m2<<"\nm3:\n"<<m3<<"\nm4:\n"<<m4;
m4=m3;
m4[0]=m4+1;
cout<<"\nm4+1:\n"<<m4;
if(m4==m3)
{
cout<<"Error !"<<endl;
}
m4 += m3;
cout<<"\nm4+m3:\n"<<m4;
cout<<"sum of m4 = "<<(double)m4<<endl;
return 0;
}
3.运行结果
1 2
8 8
m1:
1 2
8 8
m2:
2 4
2 3 4 5
0 7 0 0
m3:
9 8
7 6 5 6 4 3 6 7
5 3 5 7 3 4 9 6
2 5 9 1 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
m4:
2 4
2 3 4 5
0 0 0 0
m4+1:
9 8
104 6 5 6 4 3 6 7
5 3 5 7 3 4 9 6
2 5 9 1 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
m4+m3:
9 8
111 12 10 12 8 6 12 14
10 6 10 14 6 8 18 12
4 10 18 2 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
sum of m4 = 303
--------------------------------
Process exited after 11.75 seconds with return value 0
请按任意键继续. . .
实验总结
一. 构造和析构函数:
在实际应用中,通常需要给每个类定义构造函数。如果我们不提供构造和析构,编译器会提供编译器提供的构造函数和析构函数是空实现。
构造函数:主要作用在于创建对象时为对象的成员属性赋值,构造函数由编译器自动调用,无须手动调用。
析构函数:主要作用在于对象销毁前系统自动调用,执行一些清理工作
构造函数语法:类名(){}
a) 构造函数,没有返回值也不写void
b) 函数名称和类名相同
c) 构造函数可以有参数,因此可以发生重载
d) 程序在调用对象时候会自动调用构造,无须手动调用,并且只会调用一次
析构函数语法:~类名(){}
a) 析构函数,没有返回值也不写void
b) 函数名称与类名相同,在名称前加上符号~
c) 析构函数不可以有参数,因此不可以发生重载
d) 程序在对象销毁前会自动调用析构,无须手动调用,并且只会调用一次
构造函数的分类:
两种分类方式:
a)有参分: 有参构造和无参构造(默认构造)
b)按类型分: 普通构造和拷贝构造(const Person &p)
拷贝构造函数调用时机:
a)使用一个已经创建完毕的对象来初始化一个新对象
b)值传递的方式来给函数参数传值
c)以值的方式返回局部对象
默认情况下,C++编译器至少给一个类添加3个函数:
a)默认构造函数(无参,函数体为空)
b)默认析构函数(无参,函数体为空)
c)默认拷贝函数,对属性进行值拷贝
CMatrix(int nRow,int nCol,double pData=NULL);该构造函数为带默认参数的构造,在建立对象的时候可省去pData的实参,*pData的默认值为NULL。
二. 运算符重载:
概念:对已有德运算符重新进行定义,赋予其另一种功能,以适应不同的数据类型
本次实验中主要对:
a)算术运算符重载:+, -, +=, -=,
b)关系运算符重载:>, <, ==
c)下标操作符:[], ()
d)强制类型转换: double
e)赋值运算符:=,尤其当m1=m1的时候要特殊情况的处理:如果m1=m1,直接返回this如果不是就先Create(m.m_nRow, m.m_nCol, m.m_pData),再返回this。
CMatrix & CMatrix:: operator = (const CMatrix &m)表示一个运算符重载函数,在理解时可将operator和运算符(如operator=)视为一个函数名。
this是指向自身对象的指针,*this是自身对象。也就是说return *this返回的是当前对象的克隆或者本身(若返回类型为A, 则是克隆, 若返回类型为A&, 则是本身 )。return this返回当前对象的地址(指向当前对象的指针)。
CMatrix:: operator double()函数无需指明返回类型,double作为一个运算符,该函数用于double运算符重载。
三. 友元函数:
概念: 让一个函数或者类访问另一个类中私有成员,
特殊关键字:friend,
友元的三种实现:
• 全局函数做友元
• 类做友元
• 成员函数做友元
本次实验中用了输入输出符号的重载作为友元函数。