文章目录

  • 初识C++:CMatrix类的实现
    • 1.头文件声明 `Cmatrix.h`
    • 2.类内部方法,函数的实现 `CMatrix.cpp`
      • 2.1构造器(Constructor)
        • 2.1.1 缺省构造器
        • 2.1.2 有参构造器
      • 2.2析构函数(Destructor)
    • 2.3 `CMatrix` 对象方法
      • 2.3.1对象初始化
      • 2.3.2 对象销毁方法
    • 2.4 `CMatrix` 运算符重载
      • 2.4.1 赋值运算符重载
      • 2.4.2关系运算符重载
      • 2.4.3运算符重载
      • 2.4.4 操作符重载
    • 3.主函数测试样例`main.cpp`

初识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();// vscode
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)
{//初始化为NULL
}

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; // *this表示对象指针,因此只赋值了地址
}

外部数据流构造函数

// 外部数据流构造函数
CMatrix::CMatrix(const char * strPath):m_nRow(0),m_nCol(0),m_pData(0)
{ifstream cin(strPath); //通过ifstream定义输入流对象//将输入流地址赋值给对象指针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){// 将传入的pData赋值给类内部变量m_pData(内存拷贝的方式)memcpy(m_pData, pData, nRow*nCol*sizeof(double));}
}

2.3.2 对象销毁方法

// 销毁对象方法
void CMatrix::Release()
{//如果指针非空将其指向空if(m_pData != NULL){delete []m_pData;m_pData = NULL;}//初始化0m_nRow = m_nCol = 0;
}

2.4 CMatrix 运算符重载

在c++中,可以重定义或重载大部分内置的运算符。这样就可以使用自定义类型的运算符,实现更为复杂的运算。

重载的运算符是带有特殊名称的函数,函数名是由关键字 operator 和其后要重载的运算符符号构成的。与其他函数一样,重载运算符有一个返回类型和一个参数列表。

2.4.1 赋值运算符重载

//运算符重载(对已有运算符重新定义,赋予其另一种功能,以适应不同的数据类型)
// "="重载
CMatrix& CMatrix::operator=(const CMatrix& m)
{//如果自己对自己赋值就直接跳过,这是因为Create方法会首先调用Release(),导致原数据被释放if(this!=&m){// 这里的“=”赋值采用Create方法,是深拷贝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断言函数,对括号内的假设进行判断,假如不符合条件就抛出错误,终止程序运行// 这里的断言函数保证运算符两边的size相等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断言函数,对括号内的假设进行判断,假如不符合条件就抛出错误,终止程序运行// 这里的断言函数保证运算符两边的size相等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];
}

操作符()重载

// 操作符()重载
// a(2,5)读取矩阵a的第二行第五列
double & CMatrix::operator()(int nRow, int nCol)
{//保证下标不越界assert(nRow * m_nCol + nCol < m_nRow * m_nCol);return m_pData[nRow * m_nCol + nCol];
}

操作符”>>“重载

// 重载操作符”>>“
// 使得“>>”操作符能够读取 CMatrix 数据类型
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;
}

操作符”<<“重载

// 重载操作符”<<“
// 使得“<<”操作符能够打印 CMatrix 数据类型
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;// double data[10] = {1,2,3,4,5,6}// CMatrix ms[3] = {CMatrix(), CMatrix(), "../1.txt"}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。(这里先留一个小疑问)

还有就是对于双目运算符"+" , "-"的重载,必须定义在类的外部,否则编译过程中会报错。

【C++学习一】C++实战CMatrix类的创建相关推荐

  1. C++学习记录 实验1 CMatrix类设计与实现

    目录 一.源码实现 1.1 Main.cpp 1.2 CMatrix.cpp 1.3 CMatrix.h 二.知识小结 2.1 构造函数和析构函数 2.1.1 构造函数和析构函数的由来 2.1.2 构 ...

  2. Python3学习实战——用类实现简单的猜拳游戏

    Python3学习实战--用类实现简单的猜拳游戏 前言 本笔记仅个人认知和见解,水平有限,还请见谅. 如有错误,还请指出,若有想法,欢迎共享! 内容不代表最优解决方案,甚至可能不是很好的方法,仅供参考 ...

  3. [C++学习实验1]CMatrix类设计与实现

    一.头文件创建 1.头文件定义了CMatrix类.类內部属性.函数.以及各种调用方法 头文件定义格式如下,属于条件编译宏定义,可以根据条件选择性的只编译某段程序,也可以防止重复定义. #ifndef ...

  4. 人工智能深度学习框架MXNet实战:深度神经网络的交通标志识别训练

    人工智能深度学习框架MXNet实战:深度神经网络的交通标志识别训练 MXNet 是一个轻量级.可移植.灵活的分布式深度学习框架,2017 年 1 月 23 日,该项目进入 Apache 基金会,成为 ...

  5. Pytorch框架实战——102类花卉分类

    本篇博文为[唐宇迪]计算机视觉实训营第二天-Pytorch框架实战课程的个人笔记. 代码来自:qiuzitao深度学习之PyTorch实战(十),与视频教学流程记录一致,课程详情可参考该篇. 下文数据 ...

  6. Redis学习笔记(实战篇)(自用)

    Redis学习笔记(实战篇)(自用) 本文根据黑马程序员的课程资料与百度搜索的资料共同整理所得,仅用于学习使用,如有侵权,请联系删除 文章目录 Redis学习笔记(实战篇)(自用) 1.基于Sessi ...

  7. Tensorflow2.0深度学习入门与实战(日月光华)(学习总结1)

    Tensorflow2.0深度学习入门与实战(学习总结1) 我是刚学的,网易云课堂跟着日月光华老师,现在对每节课的学习课程做一下记录,总结,仅仅作为总结. 1.使用快捷键 shift+enter执行代 ...

  8. 深度学习_21天实战Caffe.pdf

    深度学习_21天实战Caffe.pdf 原 深度学习21天实战caffe学习笔记<1:深度学习的过往> 1. 深度学习DL: 1.1.有监督学习.无监督学习.过拟合.训练样本.泛化.训练集 ...

  9. 强烈推荐 GitHub 上值得前端学习的开源实战项目

    强烈推荐 GitHub 上值得前端学习的开源实战项目. Vue.js vue-element-admin 是一个后台前端解决方案,它基于和 element-ui 实现 基于 iView 的 Vue 2 ...

最新文章

  1. OpenCV为Halide后端安排网络
  2. 《树莓派Python编程入门与实战》——1.7 排除树莓派的故障
  3. wifi弱口令检查(2)
  4. 前端怎么使用jsessionid_前端搞微前端 | 侑夕 - 如何落地微前端一体化运营工作台...
  5. android if else语句,Android一起执行IF和ELSE语句
  6. python基础3——运算符
  7. 【蓝桥杯嵌入式】【STM32】6_ADC之LCD实时显示电压值
  8. apple_Apple WWDC 2018主题总结
  9. 数学建模——相关系数(4)——斯皮尔曼相关系数(spearman)
  10. mmsi是代表船舶什么_船舶常见的一些缩写
  11. [6.15] 心态 信念
  12. 化繁为简,弱监督目标定位领域的新SOTA - 伪监督目标定位方法(PSOL) | CVPR 2020
  13. 注解@NotEmpty、@NotBlank、@NotNull三者的区别及使用范围
  14. 记一次奇怪的网络问题
  15. 51智能小车pwm调速
  16. 论文浅尝 | PAKDD2020 - 利用支持集中匹配信息的 few shot 事件分类方法
  17. 支持C/C++、Java、python、Matlab等语言的第三方机器学习库汇总
  18. IP地址为 140.111.0.0 的B类网络,若要切割为9个子网,而且都要 连上Internet,请问子网掩码设为
  19. c语言二级培训申请书,学分申请书
  20. mysql之类型转换函数

热门文章

  1. [转]2004手机游戏年终点评
  2. Spring Boot与Log4j2集成之java.lang.IllegalStateException: Logback configuration error detected:
  3. logback异常RuntimeException in Action for tag [encoder] java.lang.NumberFormatException
  4. 【精品】JDK17下使用Ehcache3
  5. 边缘计算社区2020做了什么?
  6. 网站因服务器原因被K站,如何检查网站被百度K的原因
  7. 画直方图和函数密度曲线的几种方法
  8. 用遥控器的例子逐步介绍命令模式
  9. 修改War3分辨率的小程序
  10. 数仓数据处理与数据流向