c++矩阵类的实现.docx
《c++矩阵类的实现.docx》由会员分享,可在线阅读,更多相关《c++矩阵类的实现.docx(20页珍藏版)》请在冰豆网上搜索。
![c++矩阵类的实现.docx](https://file1.bdocx.com/fileroot1/2023-1/8/97502402-04ed-4a2d-8730-f69f3c42199d/97502402-04ed-4a2d-8730-f69f3c42199d1.gif)
c++矩阵类的实现
哈尔滨工业大学(威海)软件学院
C程序设计实验报告
编号:
姓名
孟令鑫
院系
软件学院
学号
131110412
任课教师
丁建睿
指导教师
实验地点
研究院中507-508
实验时间
2014年4月18日
实验名称
类的深入剖析
同组人
无
预习报告(对实验主要内容的认识)
得分
学会如何进行基本的运算符重载
了解运算符重载的注意事项
学会两种运算符重载的方式
学会利用运算符重载解决实际问题
矩阵操作
实验内容(问题,思路,程序,结果)
得分
实验一——实现矩阵类的操作
1、设计思路:
通过类中运算符的重载功能实现对矩阵的运算操作具体如下:
(1)运算符重载定义:
可以将已有运算符用于用户自定义数据类型(重载)
何时用:
当利用运算符重载比完成相同工作的函数调用使程序更清晰时用
意义:
C++通过重新定义运算符,使它能够用于特定类的对象执行特定功能
(2)运算符重载的几个注意事项:
运算符必须被显式重载
重载运算符只对用户自定义的类对象起作用,不
影响基本数据类型的操作。
通常分为成员函数重载和友元函数重载
重载方式;
(friend)<函数类型>operator<运算符>(<参数表>)
{
<函数体>
}
单目运算符最好重载为类的成员函数;
双目运算符则最好重载为类的友元函数。
特殊的,以下一些双目运算符不能重载为类的友元函数:
=、()、[]、->
(3)矩阵类的定义:
在private私有成员中定义row和column以及一个一维数组pt存放矩阵的行数、列数以数据成员。
(4)+、-重载:
首先定义一个中间类的对象(不分配内存),再进行两个矩阵是否能进行相加(减)的判断,既行数和列数是否相等,如果能进行相加(减)的运算则分配内存,利用for循环,将两个矩阵中对应位置上的元素相加(减)得到的结果存到中间类中,然后作为返回值返回。
如果不能进行相加(减)的,输出提示语句:
这两个矩阵不能相加或者相减,然后返回中间类对象,由于此时的中间类的对象没有分配内存,调用的时候是使用默认构造函数进行构造的,所以为0行0列的空矩阵。
(5)*重载:
首先定义一个中间类的对象(不分配内存),再进行两个矩阵是否能进行相乘的判断,既第一矩阵的列数和第二个矩阵的行数是否相等,如果能进行相加(减)的运算则分配内存,分别定义两个用来计数行和列的变量以及一个用来定位新产生的矩阵的位置的变量count,先通过外层的for循环对行数进行++操作,内层通过while循环对列进行逐次的++操作,最内层的for循环是将当前所在的第一个矩阵的行元素和第二个矩阵的列元素进行相乘累加的操作,每一次最内层的for循环结束代表着第一个矩阵的第i行和第二个矩阵的第k列的元素逐一相乘累加完毕,此时count++新产生的矩阵进行移位,进入第二个位置。
同时进入while循环,k++,当前行再和下一列进行相应的操作。
当k循环结束全部的列数之后,返回最外层的for循环,行数+1,再重复上面的操作,进行相乘并累加求和。
此时要格外注意的一点是,由于使用的一维数组,则在行数进行++操作的时候。
相应的第一个矩阵的元素要跳过column个元素,对应代码中的j=i*column一句话,然后再依次向后移位,与此对应的右侧数组则是每次跳过列数个元素(每行的元素个数)对应temp1+=m.column一句。
将数据存入对应位置,最后返回中间矩阵对象。
如果不能进行相乘的,输出提示语句:
这两个矩阵不能相加乘,然后返回中间类对象,由于此时的中间类的对象没有分配内存,调用的时候是使用默认构造函数进行构造的,所以为0行0列的空矩阵。
(6)<<重载:
利用for循环输出每一元素,如果该元素位置%列数=0说明已经循环输出完一行则输出换行符,否则继续输出。
返回地址。
(7)>>重载:
此时定义一个全局的staticcount1变量。
每一次使用重载的>>运算符则说明输入了一个矩阵,则count1++;先让用户输入行数和列数,分别赋值给右操作数的成员,将原有的数组释放,并为他重新申请内存,将用户输入的数据循环in到该对象中。
返回地址。
(8)=重载:
对应位置上的数据进行赋值。
(9)+=重载:
类似于+重载,特别的就是将左右操作数进行加的操作之后付给左操作数。
(10)==和!
=重载:
由于返回值为真假,所以要定义为bool类型,先判断行和列是否相等,如果行和列都相等了,在循环比较对应位置上的数值,如果对应位置上的数值都相等则返回真否则返回假;如果两个矩阵的行或者列不相等则直接返回假
(11)Setcount函数,当用户要重复进行使用的时候,将计数器count1置零。
2、代码设置:
《main函数》
#include
#include"Matrix.h"
usingnamespacestd;
intmain()
{
system("COLOR0a");
charchoice;
do
{
cout<<"****************************************************"<Matrixtemp;
cout<<"请输入两个矩阵"<Matrixfirst;
cin>>first;
cout<<"====================================================="<Matrixsecond;
cin>>second;
cout<<"====================================================="<temp=first+second;
cout<<"\t\t结果矩阵信息:
"<cout<cout<<"====================================================="<//
temp=first-second;
cout<<"\t\t结果矩阵信息:
"<cout<cout<<"====================================================="<//
temp=first*second;
cout<<"\t\t结果矩阵信息:
"<cout<cout<<"====================================================="<//
temp=first;
temp+=second;
cout<<"\t\t结果矩阵信息:
"<cout<cout<<"====================================================="<//
cout<<"判断两个矩阵是否相等"<if(first==second)
{
cout<<"两个矩阵相等"<}
else
{
cout<<"两个矩阵不相等"<}
temp.setcount();//将计数器重新置0
cout<<"****************************************************"<cout<<"请选择是否继续计算,是则输入y否则按其他键退出"<cout<<"****************************************************"<cin>>choice;
}while(choice=='y');
return0;
}
《Matrix.cpp》
#include"Matrix.h"
#include
staticintcount1=0;//每调用一次构造函数计数器++
usingnamespacestd;
Matrix:
:
Matrix()//默认构造函数,初始化行数列数为0.数组指针为NULL
{
row=0;
column=0;
pt=NULL;
//count++;
}
Matrix:
:
Matrix(intr,intc,double*p):
row(r),column(c)//带参构造函数,利用基类和派生类实现初始化
{
pt=newdouble[r*c];//为矩阵申请(rXc)大小的内存空间。
for(inti=0;i{
pt[i]=p[i];
}
//count++;
}
Matrix:
:
Matrix(constMatrix&m)//拷贝构造函数
{
row=m.row;
column=m.column;
pt=newdouble[row*column];//申请内存
for(inti=0;i{
pt[i]=m.pt[i];
}
//count++;
}
MatrixMatrix:
:
operator+(constMatrix&m)//矩阵的加法,利用+的运算符重载实现
{
/*if(row!
=m.row||column!
=m.column)//判断两个矩阵是否是同类型的矩阵(通过判断行数和列数是否相等)
{
cout<<"这两个矩阵不是同类型矩阵不能相加!
"<exit(0);
}*/
cout<<"两矩阵相加M1+M2=SUM"<Matrixtemp;//定义中间类temp
if((row==m.row)&&(column==m.column))
{
//Matrixtemp;//定义中间类temp
temp.pt=newdouble[row*column];//申请内存
temp.row=row;//将左操作对象的值赋给temp中间量
temp.column=column;
for(inti=0;i{
temp.pt[i]=pt[i]+m.pt[i];
}
//count++;
returntemp;//返回结果
}
else//判断两个矩阵是否是同类型的矩阵(通过判断行数和列数是否相等)
{
cout<<"这两个矩阵不是同类型矩阵不能相加!
"<//exit(0);
returntemp;
}
}
MatrixMatrix:
:
operator-(constMatrix&m)//矩阵的减法,利用-的运算符重载实现
{
/*if(row!
=m.row||column!
=m.column)//判断两个矩阵是否是同类型的矩阵(通过判断行数和列数是否相等)
{
cout<<"这两个矩阵不是同类型矩阵不能相减!
"<exit(0);
}*/
cout<<"两矩阵相减M1-M2=MIN"<Matrixtemp;
//执行减法操作
if((row==m.row)&&(column==m.column))//判断两个矩阵是否是同类型的矩阵(通过判断行数和列数是否相等)
{
temp.pt=newdouble[row*column];//申请内存
temp.row=row;
temp.column=column;
for(inti=0;itemp.pt[i]=pt[i]-m.pt[i];
returntemp;
}
else
{
cout<<"这两个矩阵不是同类型矩阵不能相减!
"<returntemp;
}
}
//矩阵乘法,利用*的运算符重载实现
MatrixMatrix:
:
operator*(constMatrix&m)
{
/*if(column!
=m.row)//判断左操作矩阵的列数与右操作矩阵的行数是否相等
{
cout<<"这两个矩阵不符合矩阵乘法条件不能相乘!
"<exit(0);
}*/
cout<<"两矩阵相乘M1*M2=pro"<Matrixtemp;//定义中间对象
if(column==m.row)
{
temp.pt=newdouble[row*m.column];//申请内存
temp.row=row;
temp.column=m.column;
//memset(temp.pt,0,sizeof(double)*row*m.column);//将temp数组的所有元素清零
temp.pt[0]=0;
intk,count,temp1;
k=count=temp1=0;
for(inti=0;i{
while(k{
for(intj=i*column/*行数×步长,也就是左数组执行一行+=操作之后,所跳过的元素个数(也就是数组含有的列数)*/;j<(i+1)*column/*到这一行的末尾位置为止*/;j++)
{
temp.pt[count]+=pt[j]*m.pt[temp1];//将左数组的行中的元素与右数组列中的元素相乘之后与新的数组中该位置的元素相加
temp1+=m.column;//右侧数组跳过c个元素
}
k++;//列数加一
temp1=k;//保存当前列数
count++;//新数组的位置加一
}
temp1=0;//列位置寄存清零
k=0;//列位置寄存清零
}
returntemp;//返回结果
}
else
{
cout<<"这两个矩阵不符合矩阵乘法条件不能相乘!
"<returntemp;
}
}
ostream&operator<<(ostream&out,constMatrix&m)//流输出运算符重载
{
cout<<"输出结果矩阵:
"<for(inti=0;i{
if((i+1)%m.column==0)//如果该元素位置%列数=0说明已经循环输出完一行则输出换行符
out<else//否则继续输出
out<}
returnout;
}
istream&operator>>(istream&in,Matrix&m)//流输入运算符重载
{
intRow,Column;
count1++;
cout<<"请输入矩阵M"<\n";
cin>>Row>>Column;//输入行数和列数
m.row=Row;//分别赋值给右操作数的成员
m.column=Column;
delete[]m.pt;//将原有的数组释放
m.pt=newdouble[Row*Column];//重新申请内存
cout<<"请按行输入"<for(inti=0;iin>>m.pt[i];
returnin;//返回地址
}
Matrix&Matrix:
:
operator=(constMatrix&m)//赋值运算符重载
{
row=m.row;
column=m.column;
pt=newdouble[row*column];
for(inti=0;ipt[i]=m.pt[i];
return*this;//返回地址
}
Matrix&Matrix:
:
operator+=(constMatrix&m)//+=运算符重载
{
/*if(row!
=m.row||column!
=m.column)//判断两个矩阵是否是同类型的矩阵(通过判断行数和列数是否相等)
{
cout<<"这两个矩阵不是同类型矩阵不能相加!
"<exit(0);
}*/
cout<<"两矩阵进行+=操作"<if((row==m.row)&&(column==m.column))
{
for(inti=0;ipt[i]+=m.pt[i];
return*this;
}
else
{
cout<<"这两个矩阵不是同类型矩阵不能相加!
"<cout<<"则输出原来的第一个矩阵M1"<return*this;
}
}
boolMatrix:
:
operator==(Matrix&right)const//判断两个矩阵是否相等
{
if((row==right.row)&&(column==right.column))//判断行和列是否相等
{
for(inti=0;i{
if(pt[i]==right.pt[i])returntrue;//如果对应位置上的数值都相等则返回真
elsereturnfalse;//否则返回假
}
}
returnfalse;//如果两个矩阵的行或者列不相等则返回假
}
Matrix:
:
~Matrix()//析构函数
{
if(pt!
=NULL)
{
delete[]pt;
pt=NULL;
}
}
/*intMatrix:
:
getcount()
{
returncount1;
}*/
intMatrix:
:
getrow()
{
returnrow;
}
intMatrix:
:
getcolumn()
{
returncolumn;
}
voidMatrix:
:
setcount()
{
count1=0;
}
《头文件》
#defineMATRIX_H_INCLUDED
#defineMAXN100
#include
#include
#include
#include
#include
#include
#ifndef_MATRIX_H
#define_MATRIX_H
#include
usingnamespacestd;
classMatrix
{
public:
//构造函数和析构函数
Matrix();
Matrix(int,int,double*);//矩阵行数、列数、数组指针
Matrix(constMatrix&);//拷贝构造函数
~Matrix();//析构函数
//运算符重载函数以及友元函数
Matrixoperator+(constMatrix&);
Matrixoperator-(constMatrix&);
Matrixoperator*(constMatrix&);
Matrix&operator=(constMatrix&);
Matrix&operator+=(constMatrix&);
friendostream&operator<<(ostream&,constMatrix&);
friendistream&operator>>(istream&,Matrix&);
booloperator==(Matrix&)const;
booloperator!
=(Matrix&right)const
{
return!
(*this==right);
}
//其他操作函数
//intgetcount();
voidsetcount();
intgetrow();
intgetcolumn();
private:
introw;
intcolumn;
double*pt;
};
#endif//MATRIX_H_INCLUDED
3、遇到问题和解决方法:
(1)==和!
=返回值问题,由于这两个是判断是否为真或者为假,则定义的返回值类型应该为bool类型
(2)count1计数器的问题,原来代码中我将count1计数器写在了构造函数中,每次调用构造函数的时候计数器++,这就导致了代码的复杂程度,这样使用中间对象的时候,就必须使用new的动态内存分配,使用之后必须马上delete释放,调用构造函数将count1--。
经过讨论,比较方便的方法就是由于重载了>>流插入运算符,由于重载的运算符只能针对类的对象使用,如果重载的>>被调用了就证明新输入了一个矩
|
|
|
|
|
|
|
|
|