[笔记]《Essential C++》第六章习题6.2
题目
练习 6.2重新以template形式实现练习4.3的Matrix class,并扩充其功能,使它能够通过heap memory(堆内存)来支持任意行列大小。分配/释放内存的操作,请在constructor/destructor中进行。
书中习题解答给出的代码
#include <iostream>
#include<fstream>
using namespace std;
template <typename elemType>
class Matrix
{
friend Matrix<elemType>
operator+(const Matrix<elemType> &, const Matrix<elemType> &);
friend Matrix<elemType>
operator*(const Matrix<elemType> &, const Matrix<elemType> &);
public:
Matrix(int rows, int columns) : _rows(rows), _cols(columns)
{
int size = _rows*_cols;
_matrix = new elemType[size];
for(int ix = 0; ix < size; ++ix)
{
_matrix[ix] = elemType();
}
}
Matrix(const Matrix&);
~Matrix(){ delete[] _matrix;}
Matrix& operator=(const Matrix&);
void operator+=(const Matrix&);
elemType& operator() (int row, int column){return _matrix[row*cols() + column];}
const elemType& operator() (int row, int column) const{return _matrix[row*cols() +column];}
int rows() const{return _rows;}
int cols() const{return _cols;}
bool same_size(const Matrix &m) const{return rows() == m.rows() && cols() == m.cols();}
bool comfortable(const Matrix &m) const{return (cols() == m.rows());}
ostream& print(ostream&) const;
protected:
int _rows;
int _cols;
elemType *_matrix;
};
template <typename elemType>
inline ostream& operator<<(ostream& os, const Matrix<elemType> &m)
{
return m.print(os);
}
// Matrix.h文件结束
template <typename elemType>
Matrix<elemType>
operator+(const Matrix<elemType> &m1, const Matrix<elemType> &m2)
{
// 确认m1和m2的大小相同
Matrix<elemType> result(m1);
result += m2;
return result;
}
template <typename elemType>
Matrix<elemType>
operator*(const Matrix<elemType> &m1, const Matrix<elemType> &m2)
{
// m1的行数(row)必须等于m2的列数(column)
Matrix<elemType> result(m1.rows(), m2.cols());
for(int ix = 0; ix < m1.rows(); ++ix)
{
for(int jx = 0; jx < m2.rows(); ++jx)
{
result(ix, jx) = 0;
for(int kx = 0; kx < m1.cols(); ++kx)
{
result(ix, jx) += m1(ix, kx) * m2(kx, jx);
}
}
}
return result;
}
template <typename elemType>
Matrix<elemType>::Matrix(const Matrix &rhs)
{
_rows = rhs._rows;
_cols = rhs._cols;
int mat_size = _rows*_cols;
_matrix = new elemType[mat_size];
for(int ix = 0; ix < mat_size; ++ix)
{
_matrix[ix] = rhs._matrix[ix];
}
}
template <typename elemType>
Matrix<elemType>& Matrix<elemType>::operator=(const Matrix &rhs)
{
// 确认m1和m2的大小相同
if(this != &rhs)
{
_rows = rhs._rows;
_cols = rhs._cols;
int mat_size = _rows*_cols;
delete[] _matrix;
_matrix = new elemType[mat_size];
for(int ix = 0; ix < mat_size; ++ix)
{
_matrix[ix] = rhs._matrix[ix];
}
}
return *this;
}
template <typename elemType>
void Matrix<elemType>::operator+=(const Matrix &m)
{
int matrix_size = cols()*rows();
for(int ix = 0; ix < matrix_size; ++ix)
{
(*(_matrix + ix)) += (*(m._matrix + ix));
}
}
template <typename elemType>
ostream& Matrix<elemType>::print(ostream &os) const
{
int col = cols();
int matrix_size = col*rows();
for(int ix = 0; ix < matrix_size; ++ix)
{
if(ix % col == 0) os << endl;
os << (*(_matrix + ix)) << ' ';
}
os << endl;
return os;
}
int main()
{
ofstream log("log.txt");
if(!log)
{
cerr << "can't open log file!\n";
return 0;
}
Matrix<float> identity(4, 4);
log << "identity: " << identity << endl;
float ar[16] = {1., 0., 0., 0., 0., 1., 0., 0.,
0., 0., 1., 0., 0., 0., 0., 1. };
for(int i = 0, k = 0; i < 4; ++i)
{
for(int j = 0; j < 4; ++j)
{
identity(i, j) = ar[k++];
}
}
log << "identity after set: " << identity << endl;
Matrix<float> m(identity);
log << "m: memberwise initialized: " << m << endl;
Matrix<float> m2(8, 12);
log << "m2: 8x12: " << m2 << endl;
m2 = m;
log << "m2 after memberwise assigned to m: " << m2 << endl;
float ar2[16] = {1.3, 0.4, 2.6, 8.2, 6.2, 1.7, 1.3, 8.3,
4.2, 7.4, 2.7, 1.9, 6.3, 8.1, 5.6, 6.6 };
Matrix<float> m3(4,4);
for(int i = 0, k = 0; i < 4; ++i)
{
for(int j = 0; j < 4; ++j)
{
m3(i, j) = ar2[k++];
}
}
log << "m3: assigned random values: " << m3 << endl;
Matrix<float> m4 = m3*identity;
log << "result of m3*identity: " << m4 << endl;
Matrix<float> m5 = m3 + m4;
log << "result of m3 + m4: " << m5 << endl;
m3 += m4;
log << "m3: plus with m4: " << m3 << endl;
}
在我运行上面的程序之后,编译器直接报错,报错信息是
undefined reference to `operator*(Matrix<float> const&, Matrix<float> const&)'
以及
undefined reference to `operator+(Matrix<float> const&, Matrix<float> const&)'
这两个函数是Matrix的友元函数,按理说将其声明写在类定义中,定义写在外面应该是可以的,但是注意,在上面的类定义中,并没有声明这两个友元函数是模板函数,但是在后面的定义中,用的却是模板函数的定义,所以我们只要在声明时加上模板就行了,注意不要用和Matrix的模板参数名称一样的模板参数名,会导致下面的编译错误:
error: declaration of template parameter 'elemType' shadows template parameter
正确代码
#include <iostream>
#include<fstream>
using namespace std;
template <typename elemType>
class Matrix
{
template <typename T>
friend Matrix<T>
operator+(const Matrix<T> &, const Matrix<T> &);
template <typename T>
friend Matrix<T>
operator*(const Matrix<T> &, const Matrix<T> &);
public:
Matrix(int rows, int columns) : _rows(rows), _cols(columns)
{
int size = _rows*_cols;
_matrix = new elemType[size];
for(int ix = 0; ix < size; ++ix)
{
_matrix[ix] = elemType();
}
}
Matrix(const Matrix&);
~Matrix(){ delete[] _matrix;}
Matrix& operator=(const Matrix&);
void operator+=(const Matrix&);
elemType& operator() (int row, int column){return _matrix[row*cols() + column];}
const elemType& operator() (int row, int column) const{return _matrix[row*cols() +column];}
int rows() const{return _rows;}
int cols() const{return _cols;}
bool same_size(const Matrix &m) const{return rows() == m.rows() && cols() == m.cols();}
bool comfortable(const Matrix &m) const{return (cols() == m.rows());}
ostream& print(ostream&) const;
protected:
int _rows;
int _cols;
elemType *_matrix;
};
template <typename elemType>
inline ostream& operator<<(ostream& os, const Matrix<elemType> &m)
{
return m.print(os);
}
// Matrix.h文件结束
template <typename elemType>
Matrix<elemType>
operator+(const Matrix<elemType> &m1, const Matrix<elemType> &m2)
{
// 确认m1和m2的大小相同
Matrix<elemType> result(m1);
result += m2;
return result;
}
template <typename elemType>
Matrix<elemType>
operator*(const Matrix<elemType> &m1, const Matrix<elemType> &m2)
{
// m1的行数(row)必须等于m2的列数(column)
Matrix<elemType> result(m1.rows(), m2.cols());
for(int ix = 0; ix < m1.rows(); ++ix)
{
for(int jx = 0; jx < m2.rows(); ++jx)
{
result(ix, jx) = 0;
for(int kx = 0; kx < m1.cols(); ++kx)
{
result(ix, jx) += m1(ix, kx) * m2(kx, jx);
}
}
}
return result;
}
template <typename elemType>
Matrix<elemType>::Matrix(const Matrix &rhs)
{
_rows = rhs._rows;
_cols = rhs._cols;
int mat_size = _rows*_cols;
_matrix = new elemType[mat_size];
for(int ix = 0; ix < mat_size; ++ix)
{
_matrix[ix] = rhs._matrix[ix];
}
}
template <typename elemType>
Matrix<elemType>& Matrix<elemType>::operator=(const Matrix &rhs)
{
// 确认m1和m2的大小相同
if(this != &rhs)
{
_rows = rhs._rows;
_cols = rhs._cols;
int mat_size = _rows*_cols;
delete[] _matrix;
_matrix = new elemType[mat_size];
for(int ix = 0; ix < mat_size; ++ix)
{
_matrix[ix] = rhs._matrix[ix];
}
}
return *this;
}
template <typename elemType>
void Matrix<elemType>::operator+=(const Matrix &m)
{
int matrix_size = cols()*rows();
for(int ix = 0; ix < matrix_size; ++ix)
{
(*(_matrix + ix)) += (*(m._matrix + ix));
}
}
template <typename elemType>
ostream& Matrix<elemType>::print(ostream &os) const
{
int col = cols();
int matrix_size = col*rows();
for(int ix = 0; ix < matrix_size; ++ix)
{
if(ix % col == 0) os << endl;
os << (*(_matrix + ix)) << ' ';
}
os << endl;
return os;
}
int main()
{
ofstream log("log.txt");
if(!log)
{
cerr << "can't open log file!\n";
return 0;
}
Matrix<float> identity(4, 4);
log << "identity: " << identity << endl;
float ar[16] = {1., 0., 0., 0., 0., 1., 0., 0.,
0., 0., 1., 0., 0., 0., 0., 1. };
for(int i = 0, k = 0; i < 4; ++i)
{
for(int j = 0; j < 4; ++j)
{
identity(i, j) = ar[k++];
}
}
log << "identity after set: " << identity << endl;
Matrix<float> m(identity);
log << "m: memberwise initialized: " << m << endl;
Matrix<float> m2(8, 12);
log << "m2: 8x12: " << m2 << endl;
m2 = m;
log << "m2 after memberwise assigned to m: " << m2 << endl;
float ar2[16] = {1.3, 0.4, 2.6, 8.2, 6.2, 1.7, 1.3, 8.3,
4.2, 7.4, 2.7, 1.9, 6.3, 8.1, 5.6, 6.6 };
Matrix<float> m3(4,4);
for(int i = 0, k = 0; i < 4; ++i)
{
for(int j = 0; j < 4; ++j)
{
m3(i, j) = ar2[k++];
}
}
log << "m3: assigned random values: " << m3 << endl;
Matrix<float> m4 = m3*identity;
log << "result of m3*identity: " << m4 << endl;
Matrix<float> m5 = m3 + m4;
log << "result of m3 + m4: " << m5 << endl;
m3 += m4;
log << "m3: plus with m4: " << m3 << endl;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!