栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

「C++学习一」C++实战CMatrix类的创建

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

「C++学习一」C++实战CMatrix类的创建

文章目录
  • 初识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 
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;
    }
    //初始化0
    m_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 

“!=“运算符重载

// !=运算符重载
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 

"-="重载

// "-="重载
CMatrix& CMatrix::operator-=(const CMatrix& m)
{
    //assert断言函数,对括号内的假设进行判断,假如不符合条件就抛出错误,终止程序运行
    // 这里的断言函数保证运算符两边的size相等
    assert(m_nRow==m.m_nRow && m_nCol==m.m_nCol);
    for (int i=0;i 

"+"重载

// "+"重载
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 

操作符()重载

// 操作符()重载
// 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_pData[i];
    }
    return is;
}

操作符”<<“重载

// 重载操作符”<<“
// 使得“<<”操作符能够打印 CMatrix 数据类型
ostream & operator<<(ostream& os, const CMatrix &m)
{
    os<<"size:["< 

重载强制类型转换

// 重载强制类型转换
CMatrix::operator double()
{
    double dS=0;
    // 将类型转换重载为矩阵所有元素相加
    for(int i=0;i 
3.主函数测试样例main.cpp 
#include 
#include 
#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< 

运行结果:

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。(这里先留一个小疑问)

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

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/304335.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号