4. Mátrix osztály

Czirkos Zoltán · 2019.02.27.

#include <iostream>
#include <iomanip>
#include <stdexcept>

class Matrix {
    private:
        // Tervezési szempont: mivel az adattagok privátak,
        // megtehetjük, hogy 2D dinamikus tömb helyett 1D
        // tömböt használunk, és mi magunk végezzük el a
        // 2D->1D leképezést az indexelésnél. Ez nagyban
        // leegyszerűsíti az összes függvényt!
        int sz, m;
        double* adat;
    public:
        // Elvárt konstruktorok
        Matrix();
        Matrix(int sz, int m);

        // Erőforráskezelés miatt szükséges függvények
        Matrix(Matrix const & orig);
        Matrix& operator=(Matrix const & orig);
        ~Matrix();

        int get_sz() const { return sz; }
        int get_m() const { return m; }

        // Két indexet kapó indexelő operátor nincsen,
        // ezért a függvényhívó operátort használjuk majd
        // indexeléshez. Pl. m(1, 2) = 5.7;
        double & operator() (int x, int y);
        double const & operator() (int x, int y) const;

        Matrix operator+(const Matrix & rhs) const;
};


Matrix::Matrix() {
    sz = 0;
    m = 0;
    adat = NULL;
}

Matrix::Matrix(int sz, int m)
    : sz(sz), m(m), adat(new double[sz*m])
{
    for (int i = 0; i < sz*m; ++i)
        adat[i] = 0.0;
}

Matrix::~Matrix() {
    delete[] adat;
}

Matrix::Matrix(Matrix const & orig) {
    // Másoló konstruktor: visszavezetjük az értékadó
    // operátorra. Csak az abban lévő "delete[] adat"-ot
    // kell hatástalanítani, amúgy ugyanazt csinálja.
    adat = NULL;
    *this = orig;
}

Matrix & Matrix::operator=(Matrix const & orig) {
    if (this != &orig) {
        delete[] adat;
        sz = orig.sz;
        m = orig.m;
        adat = new double[sz*m];
        for (int i = 0; i < sz*m; ++i)
            adat[i] = orig.adat[i];
    }
    return *this;
}

double & Matrix::operator() (int x, int y) {
    if (x >= sz || x < 0 || y >= m || y < 0)
        throw std::out_of_range("matrix tulindex");
    return adat[y*sz+x];
}

// Ugyanaz mint a fenti, csak konstans mátrixra.
double const & Matrix::operator() (int x, int y) const {
    if (x >= sz || x < 0 || y >= m || y < 0)
        throw std::out_of_range("matrix tulindex");
    return adat[y*sz+x];
}

std::ostream & operator<< (std::ostream & os, Matrix const & m) {
    for (int y = 0; y < m.get_m(); y++) {
        for (int x = 0; x < m.get_sz(); x++)
            os << std::setw(10) << m(x, y) << ' ';
        os << std::endl;
    }
    return os;
}

Matrix Matrix::operator+(Matrix const & rhs) const {
    if (sz != rhs.sz || m != rhs.m)
        throw std::out_of_range("matrix operator+ nem egyforma meret");
    Matrix osszeg(sz, m);
    for (int i = 0; i < sz*m; ++i)
        osszeg.adat[i] = adat[i] + rhs.adat[i];
    return osszeg;
}

int main() {
    Matrix m1(3, 3);

    m1(1, 2) = 5.7;
    m1(2, 0) = 125.7;
    std::cout << m1(1, 2) << std::endl;

    Matrix m2;
    m2 = m1+m1;
    std::cout << m1;
    std::cout << m2;

    return 0;
}