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

一、源码实现

1.1 Main.cpp

#include<iostream>
using namespace std;
#include"CMatrix.h"
int main()
{
    double pData[10] = { 2,3,4,5 };
    CMatrix m1, m2(2, 5, pData);
    cin >> m1;
    m2.Set(1, 3, 10);
    cout << m1 << m2;
    CMatrix ms[4] = { CMatrix(),CMatrix(2,5,pData),CMatrix(ms[1]),CMatrix("C:\\1.txt") };
    cout << ms[1] << ms[2];
    if (ms[1] != ms[2])
    {
        cout << "Error occur!" << endl;
    }
    ms[1] += ms[2];
    ms[1][1] = 100;
    ms[1](1, 1) = 50;
    cout << ms[1];
    cout << "sum of m1=" << double(ms[1]);
    double d = 1.2;
    int i = int(d);
    return 0;
}


1.2 CMatrix.cpp

#include "CMatrix.h"
#include<fstream>
#include<assert.h>
CMatrix::CMatrix()
{
    m_nRow = m_nCol = 0;
    m_pData = 0;
}
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;
}
CMatrix::CMatrix(const char* strPath)
{
    m_pData = 0;
    m_nRow = m_nCol = 0;
    ifstream cin(strPath);
    cin >> *this;
}
CMatrix::~CMatrix() {
    Release();
}
bool CMatrix::Create(int nRow, int nCol, double* pData) {
    Release();
    m_pData = new double[nRow * nCol];
    m_nRow = nRow;
    m_nCol = nCol;
    if (pData)
    {
        memcpy(m_pData, pData, nRow * nCol * sizeof(double));
    }
    return true;
}
void CMatrix::Release() {
    if (m_pData)
    {
        delete[]m_pData;
        m_pData = NULL;
    }
    m_nRow = m_nCol = 0;
}
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;
}
ostream& operator<<(ostream& os, const CMatrix& m)
{
    os << 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& CMatrix::operator=(const CMatrix& m)
{
    if (this != &m) {
        Create(m.m_nRow, m.m_nCol, m.m_pData);
    }
    return*this;
}
CMatrix& CMatrix::operator+=(const CMatrix& m)
{
    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;
}
double& CMatrix::operator[](int nIndex)
{
    assert(nIndex < m_nRow* m_nCol);
    return m_pData[nIndex];
}
double& CMatrix::operator()(int nRow, int nCol)
{
    assert(nRow * m_nCol * nCol + nCol < m_nRow* m_nCol);
    return m_pData[nRow * m_nCol + nCol];
}
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);
}
CMatrix::operator double()
{
    double ds = 0;
    for (int i = 0; i < m_nRow * m_nCol; i++)
    {
        ds += m_pData[i];
    }
    return ds;
}


1.3 CMatrix.h

#pragma once
#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 Set(int nRow, int nCol, double dVale);
    void Release();
    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);
    double& operator[](int nIndex);
    double& operator()(int nRow, int nCol);
    bool operator==(const CMatrix& m);
    bool operator!=(const CMatrix& m);
    operator double();
private:
    int m_nRow;
    int m_nCol;
    double* m_pData;
};
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;
}


运行结果:
在这里插入图片描述
图1.1

二、知识小结

2.1 构造函数和析构函数

2.1.1 构造函数和析构函数的由来

   类的数据成员不能在类的声明时候初始化,为了解决这个问题? 使用构造函数处理对对象的初始化。构造函数是一种特殊的成员函数,与其他函数不同,不需要用户调用它,而是创建对象的时候自动调用。析构函数是对象不再使用的时候,需要清理资源的时候调用。

2.1.2 构造函数和析构函数的基本语法

  • A.构造函数
    • C++中的类需要定义与类名相同的特殊成员函数时,这种与类名相同的成员函数叫做构造函数;
    • 构造函数可以在定义的时候有参数;
    • 构造函数没有任何返回类型;
    • 构造函数的调用: 一般情况下,C++编译器会自动的调用构造函数。特殊情况下,需要手工的调用构造函数。
class Test
{
   public:
   //构造函数
   Test()
   {

   }
}
  • B.析构函数
    • C++中的类可以定义一个特殊的成员函数清理对象,这个特殊的函数是析构函数;
    • 析构函数没有参数和没有任何返回类型;
    • 析构函数在对象销毁的时候自动调用;
    • 析构函数调用机制: C++编译器自动调用。
class Test
{
  ~Test()
  {

  }
}

2.1.3 构造函数的分类和调用

  • A.无参构造函数
class Test
{
  private:
       int x;
  public:
       Test()
       {
         this->x=10;
       }
}
- Test a(10); 调用有参数构造函数
  • B.有参构造函数
class Test
{
  private:
       int x;
  public:
       Test(int x)
       {
         this->x=x;
       }
}

有参数构造函数的调用时机:

- Test a(10); 调用有参数构造函数
- Test b=(2,3); 逗号表达式的值是最后一位,调用有参数构造函数
- Test c=Test(2); 产生一个匿名对象,直接转化成c(只会调用一次有参数构造函数)

2.1.4 构造函数和析构函数的小结

a. 构造函数时C++中用于初始化对象状态的特殊函数;
b. 构造函数在对象创建的时候自动调用;
c. 构造函数和普通成员函数都遵循重载原则;
d. 拷贝构造函数是对象正确初始化的重要保障;
e. 必要的时候必须手工的写拷贝构造函数。

2.2 友元函数

2.2.1 什么是友元函数

在实现类之间数据共享时,减少系统开销,提高效率。如果类A中的函数要访问类B中的成员(例如:智能指针类的实现),那么类A中该函数要是类B的友元函数。
具体来说:为了使其他类的成员函数直接访问该类的私有变量。即:允许外面的类或函数去访问类的私有变量和保护变量,从而使两个类共享同一函数。

2.2.2 使用友元函数的优缺点

优点:能够提高效率,表达简单、清晰。

缺点:友元函数破环了封装机制,尽量不使用成员函数,除非不得已的情况下才使用友元函数。

2.2.3 语法

声明: friend + 普通函数声明

实现位置:可以在类外或类中

实现代码:与普通函数相同

调用:类似普通函数,直接调用

2.3 运算符重载

2.3.1 运算符重载的概念理解如果不做特殊处理,C++ 的 +、-、*、/ 等运算符只能用于对基本类型的常量或变量进行运算,不能用于对象之间的运算。

有时希望对象之间也能用这些运算符进行运算,以达到使程序更简洁、易懂的目的。例如,复数是可以进行四则运算的,两个复数对象相加如果能直接用+运算符完成,这样显得很直观和简洁。
利用 C++ 提供的“运算符重载”机制,赋予运算符新的功能,就能解决用+将两个复数对象相加这样的问题。
运算符重载,就是对已有的运算符赋予多重含义,使同一运算符作用于不同类型的数据时产生不同的行为。运算符重载的目的是使得 C++ 中的运算符也能够用来操作对象。
运算符重载的实质是编写以运算符作为名称的函数。不妨把这样的函数称为运算符函数。运算符函数的格式如下:

返回值类型  operator  运算符(形参表)
{
    ....
}

2.3.2 运算符重载为友元函数

一般情况下,将运算符重载为类的成员函数是较好的选择。但有时,重载为成员函数不能满足使用要求,重载为全局函数又不能访问类的私有成员,因此需要将运算符重载为友元。

例如,对于复数类 Complex 的对象,希望它能够和整型以及实数型数据做四则运算,假设 c 是 Complex 对象,希望c+5和5+c这两个表达式都能解释得通。

将+重载为 Complex 类的成员函数能解释c+5,但是无法解释5+c。要让5+c有意义,则应对+进行再次重载,将其重载为一个全局函数。为了使该全局函数能访问 Complex 对象的私有成员,就应该将其声明为 Complex 类的友元。具体写法如下:

class Complex
{
    double real, imag;
public:
    Complex(double r, double i):real(r), imag(i){};
    Complex operator + (double r);
    friend Complex operator + (double r, const Complex & c);
};
Complex Complex::operator + (double r)
{ //能解释c+5
    return Complex(real+r, imag);
}
Complex operator + (double r, const Complex & c)
{ //能解释5+c
    return Complex (c.real+r, c.imag);
}

本次实验中,通过构造函数,析构函数,运算符重载和友元函数四个方面进行了设计,通过实战,掌握了以上知识点。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的CMatrix实现,包含了加、减、点乘、点除运算的成员函数和运算符重载: ```c++ #include <iostream> #include <vector> using namespace std; class CMatrix { private: vector<vector<double>> mat; int rows, cols; public: // 构造函数 CMatrix(int r, int c) : rows(r), cols(c) { mat.resize(rows); for (int i = 0; i < rows; i++) { mat[i].resize(cols); } } // 获取矩阵元素 double& operator()(int i, int j) { return mat[i][j]; } // 矩阵加法 CMatrix operator+(CMatrix& other) { CMatrix res(rows, cols); for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { res(i, j) = mat[i][j] + other(i, j); } } return res; } // 矩阵减法 CMatrix operator-(CMatrix& other) { CMatrix res(rows, cols); for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { res(i, j) = mat[i][j] - other(i, j); } } return res; } // 矩阵点乘 CMatrix operator*(CMatrix& other) { if (cols != other.rows) { throw "Invalid matrix dimensions!"; } CMatrix res(rows, other.cols); for (int i = 0; i < rows; i++) { for (int j = 0; j < other.cols; j++) { double sum = 0; for (int k = 0; k < cols; k++) { sum += mat[i][k] * other(k, j); } res(i, j) = sum; } } return res; } // 矩阵点除 CMatrix operator/(CMatrix& other) { if (cols != other.cols || rows != other.rows) { throw "Invalid matrix dimensions!"; } CMatrix res(rows, cols); for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { res(i, j) = mat[i][j] / other(i, j); } } return res; } }; int main() { CMatrix a(2, 2); a(0, 0) = 1; a(0, 1) = 2; a(1, 0) = 3; a(1, 1) = 4; CMatrix b(2, 2); b(0, 0) = 5; b(0, 1) = 6; b(1, 0) = 7; b(1, 1) = 8; // 矩阵加法 CMatrix c = a + b; cout << "加法结果:" << endl; for (int i = 0; i < c.rows; i++) { for (int j = 0; j < c.cols; j++) { cout << c(i, j) << " "; } cout << endl; } // 矩阵减法 CMatrix d = a - b; cout << "减法结果:" << endl; for (int i = 0; i < d.rows; i++) { for (int j = 0; j < d.cols; j++) { cout << d(i, j) << " "; } cout << endl; } // 矩阵点乘 CMatrix e = a * b; cout << "点乘结果:" << endl; for (int i = 0; i < e.rows; i++) { for (int j = 0; j < e.cols; j++) { cout << e(i, j) << " "; } cout << endl; } // 矩阵点除 CMatrix f = a / b; cout << "点除结果:" << endl; for (int i = 0; i < f.rows; i++) { for (int j = 0; j < f.cols; j++) { cout << f(i, j) << " "; } cout << endl; } return 0; } ``` 运行结果: ``` 加法结果: 6 8 10 12 减法结果: -4 -4 -4 -4 点乘结果: 19 22 43 50 点除结果: 0.2 0.333333 0.428571 0.5 ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值