学习任务:
介绍概念:宏。变量revisited(局部变量及作用域,函数的形参及实参,按值传递及按地址传递), 编程style, void *类型,变量命名。程序组织(函数/文件/项目);缺省参数
选介绍:类(OOP),类的封装性,new/delete操作符,构造,析构
练习:
使用类重复第一课任务,Matrix.文件:main(). 第2套:matrix.h, matrix.cpp
要求:矩阵加法,矩阵乘法。建议在析构里free空间
头文件 Matrix.h
#ifndef Matrix_h_
#define Matrix_h_
class Matrix
{
private:
int column; //矩阵的列数
int row; //矩阵的行数
int** pointer; //矩阵的内存的首地址
public:
Matrix( ); //构造函数
Matrix::Matrix( int row , int col ); //带参数的构造函数
Matrix::Matrix( const Matrix & A ); //复制构造函数
~Matrix( ); //析构函数
void set( ); //输入矩阵
void show( ) const; //显示矩阵 类方法不修改调用对象,就应该将其声明为const
int get_row( ) const; //得到矩阵行数
int get_col( ) const; //得到矩阵列数
Matrix add ( const Matrix & A ) const; //矩阵相加 参数声明为const,确保参数不被修改
Matrix mulp( const Matrix & A ) const; //矩阵相乘
Matrix operator+( const Matrix & A ); //重载‘+’
Matrix operator*( const Matrix & A ); //重载‘*’
Matrix & Matrix::operator=( const Matrix & A ); //重载‘=’
};
#endif
函数文件 Matrix.cpp
/****************************************************************
*只要类方法不修改调用对象,就应该将其声明为const
*就像 void show()const
*在构造函数中使用new时应注意的事项:
*如果在构造函数中使用new来初始化指针成员,则应在析构函数中使用delete
*new和delete必须相互兼容,new对应delete,new[]对应delete[]
*如果有多个构造函数,则必须以相同的方式使用new,要么都带[],要么都不带,还必须与析构函数兼容
*应定义一个复制构造函数,通过深度复制将一个对象初始化为另一个对象
*复制构造函数应分配足够的空间来存储复制的数据,并复制数据,而不仅仅是数据的地址,另外,应更新所有受影响的静态类成员
*应定义一个赋值操作符,通过深度复制将一个对象初始化为另一个对象
*具体来说,该方法赢完成以下任务:检查自我赋值的情况,释放成员指针以前指向的内存,复制数据而不仅仅是数据的地址并返回一个指向调用对象的引用
****************************************************************/
#include<iostream>
#include"Matrix.h"
using namespace std;
Matrix::Matrix( ) //默认构造函数
{
printf( "调用构造函数1\n" );
row = 0;
column = 0;
pointer = NULL;
}
Matrix::Matrix( int row , int col ) //在构造函数中分配内存
{
printf( "调用构造函数2\n" );
this->row = row;
this->column = col;
pointer = new int*[row];
for( int i = 0; i < row; i++ )
{
pointer[i] = new int[column];
}
for( int i = 0; i < row; i++ )
{
for( int j = 0; j < column; j++ )
{
pointer[i][j] = 0;
}
}
}
Matrix::Matrix( const Matrix & A ) //复制构造函数
{
printf( "调用复制构造函数\n" );
this->row = A.row;
this->column = A.column;
pointer = new int*[row];
for( int i = 0; i < row; i++ )
{
pointer[i] = new int[column];
}
for( int i = 0; i < row; i++ ) //深度复制
{
for( int j = 0; j < column; j++ )
{
pointer[i][j] = A.pointer[i][j];
}
}
}
Matrix::~Matrix( ) //析构函数,释放矩阵内存
{
for( int i = 0; i < row; i++ )
{
delete[] pointer[i];
}
delete[] pointer;
pointer = NULL;
printf( "调用析构函数\n" );
}
/*******************************************************************
函数名称:get_row
函数参数:无
返回参数:无
函数功能:得到矩阵的行数
调用方法:无
*******************************************************************/
int Matrix::get_row( ) const
{
return this->row;
}
/*******************************************************************
函数名称:get_col
函数参数:无
返回参数:无
函数功能:得到矩阵的列数
调用方法:无
*******************************************************************/
int Matrix::get_col( ) const
{
return this->column;
}
/*******************************************************************
函数名称:show
函数参数:无
返回参数:无
函数功能:显示矩阵
调用方法:无
*******************************************************************/
void Matrix::show( ) const
{
printf( "This matrix(%d*%d) is as followed:\n" , row , column );
for( int i = 0; i < row; i++ )
{
for( int j = 0; j < column; j++ )
{
printf( "%3d" , pointer[i][j] );
}
printf( "\n" );
}
}
/*******************************************************************
函数名称:set
函数参数:无
返回参数:无
函数功能:输入矩阵
调用方法:create()
*******************************************************************/
void Matrix::set( )
{
printf( "\nPlease input the matrix:\n" );
for( int i = 0; i < row; i++ )
{
for( int j = 0; j < column; j++ )
{
scanf_s( "%d" , &pointer[i][j] );
}
}
}
/*******************************************************************
函数名称:add
函数参数:另一个作为加数的矩阵,以及存放结果的引用
返回参数:无
函数功能:计算两矩阵的和
调用方法:create()
*******************************************************************/
Matrix Matrix::add( const Matrix& A ) const
{
Matrix result( this->row , A.column );
for( int i = 0; i < row; i++ )
{
for( int j = 0; j < column; j++ )
{
result.pointer[i][j] = this->pointer[i][j] + A.pointer[i][j];
}
}
return result;
}
/*******************************************************************
函数名称:mulp
函数参数:另一个作为乘数的矩阵,以及存放结果的引用
返回参数:无
函数功能:计算两矩阵的积
调用方法:create()
*******************************************************************/
Matrix Matrix::mulp( const Matrix& A ) const
{
int sum = 0;
Matrix result( this->row , A.column );
for( int i = 0; i < result.row; i++ )
{
for( int j = 0; j < result.column; j++ )
{
sum = 0;
int m = 0;
for( int k = 0; k < A.row; k++ )
{
sum = sum + this->pointer[i][m] * A.pointer[k][j];
m++;
}
result.pointer[i][j] = sum;
}
}
return result;
}
Matrix Matrix::operator+( const Matrix & A ) //重载 '+'
{
Matrix result( this->row , A.column );
for( int i = 0; i < this->row; i++ )
{
for( int j = 0; j < this->column; j++ )
{
result.pointer[i][j] = this->pointer[i][j] + A.pointer[i][j];
}
}
return result;
}
Matrix & Matrix::operator=( const Matrix & A ) //重载 '='
{
if( this == &A ) //检查是否为自身
{
return *this;
}
for( int i = 0; i < row; i++ ) //释放以前的内存
{
if( pointer[i] != NULL )
delete[] pointer[i];
}
delete[] pointer;
this->row = A.row;
this->column = A.column;
pointer = new int*[row];
for( int i = 0; i < row; i++ ) //申请内存
{
pointer[i] = new int[column];
}
for( int i = 0; i < this->row; i++ ) //深度复制
{
for( int j = 0; j < this->column; j++ )
{
this->pointer[i][j] = A.pointer[i][j];
}
}
return *this;
}
Matrix Matrix::operator*( const Matrix & A ) //重载 '*'
{
int sum = 0;
Matrix result( this->row , A.column );
for( int i = 0; i < result.row; i++ )
{
for( int j = 0; j < result.column; j++ )
{
sum = 0;
int m = 0;
for( int k = 0; k < A.row; k++ )
{
sum = sum + this->pointer[i][m] * A.pointer[k][j];
m++;
}
result.pointer[i][j] = sum;
}
}
return result;
}
这个也算是2.0版本,第一次写把作为结果的对象的引用也作为参数传入方法当中,后来看着特别别扭,于是学习了重载操作符等。
对于这个版本,特别要注意的就是对于复制构造函数的定义和“=”的重载的定义。
另外,之前想把分配内存和释放内存单独作为private函数使用,不在构造函数中分配内存。比如做乘法的时候先定义一个对象,对这个对象单独申请一块内存,然后进行计算什么的,再return这个对象。但是失败了,在return对象的时候调用了析构函数,我还没弄明白。
知识点:类,对象,构造函数,析构函数,重载,引用