IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C++学习记录 实验1 CMatrix类设计与实现 -> 正文阅读

[C++知识库]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);
}

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

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-10-01 16:38:20  更:2021-10-01 16:40:10 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 18:44:23-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码