Klasy, destruktory, konstruktory C++

0

Hej, właśnie przechodze przez początki początków mojego programowania z C++, szczególnie, że zdalne nauczanie utrudnia wszelkie kontakty więc przychodzę z pomocą tutaj.

Wykonałam czesciowo polecenie ale siedze nad tym dzis tak długo, że zmieniałam wszystko pare razy i juz sama sie pogubiłam we własnym kodzie. Dosięgło mnie zwątpienie i potrzebuje naprowadzenia na prawidłową ścieżkę.
Wiem, że kod to totalny chaos a poziom jest absurdalny, ale za każdą pomoc bede wdzieczna!
Tutaj treść polecenia:

Zdefiniuj klasę opisującą macierz liczb rzeczywistych - tablica dwuwymiarowa M x N - przechowywana (alokowana dynamicznie) wewnetrznie pod podwójnym wskaźnikiem. Dla klasy należy zdefiniować nastepujące funkcje:

  • konstruktor domyslny
  • konstruktor tworzacy macierz o zadanych rozmiarach
  • konstruktor tworzący macierz na podstawie tablicy przekazanej jako argument konstruktora
  • konstruktor kopiujacy
  • destruktor
  • funkcje zmieniajaca rozmiar przechowywanej macierzy
  • funkcje zwracajaca ilość kolumn
  • funkcje zwracajaca ilość wierszy
  • funkcje generujaca macierz losowa z zakresu od 0.0 do 1.0
  • funkcje wypisujaca przechowywana macierz na ekranie

Napisac przykladowy program wykorzystujacy napisana klase.

#ifndef _HEADER_
#define _HEADER_

using namespace std;

class Macierz
{
public:
	Macierz(); //Domyslny konstruktor A
	Macierz(int m, int n); //Konstruktor tworzacy o zadanych rozmiarach n i m B
	Macierz(const Macierz& wzor); //Kontruktor kopiujący
	
	~Macierz(); //Destruktor

private:
	int m, n;
	int** p;

	//alokacja pamieci tablicy
	void allocTab()
	{
		p = new int* [m];
		for (int i = 0; i < m; i++)
		{
			p[i] = new int[n];
		}
	}
};

#endif
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <cstdio>
#include "header.h"

using namespace std;

int main()
{
	int r;
	int c;

	cout << "podaj pierwszy wymiar" << endl;
	cin >> r;
	cout << "podaj drugi wymiar" << endl;
	cin >> c;

	Macierz object;

	//tworzenie tablicy dynamicznej
	int** macierz = new int* [r];
	for (int j = 0; j < r; j++)
	{
		macierz[j] = new int[c];
	}



    while (1) {
        clcscr();
        wypiszMacierz(int m, int n);
        cout << "\n Polecenia \n";
        cout << "\n 1) Zmien rozmiar macierzy";
        cout << "\n 2) Wyswietl liczbe kolumn";
        cout << "\n 3) Wyswietl liczbe wierszy";
        cout << "\n 4) Wyswietl macierz";
        cout << "\n 5) Exit.";
       
        cin >> w;
        switch (w) {
        case 1:
            Zmienrozmiar();
            break;
        case 2:
            lkolumn();
            break;
        case 3:
            lwierszy();
            break;
        case 4:
            Macierz::wypiszMacierz()
            break;
        case 5:
            exit(1);
        default:
            cout << "\n Nieprrawidlowy wybor";
        } // koniec switcha
        getch();
    } // koniec while



	void wypelnijMacierz(int m_, int n_);
	object.wypiszMacierz();

	return 0;
}
#include "header.h"
#include <iostream>
using namespace std;

//Domyslny konstruktor A
Macierz::Macierz() : Macierz(0, 0) {}

//Konstruktor tworzacy B
Macierz::Macierz(int m, int n)
{

	if (n<0 || m<0)
	{
		cout << "blad" << endl;
	}

	allocTab();
	for (int i = 0; i < m; i++)
	{
		for (int j = 0; j < n; j++)
		{
			p[i][j] = 0;
		}
	}
}

Macierz::Macierz(const Macierz& wzor) {
	m = wzor.m;
	n = wzor.n;
	cout << "Konstruktor kopiujacy dziala" << endl;
}

//Destruktor
Macierz::~Macierz()
{
	for (int i = 0; i < m; i++)
	{
		delete[] p[i];
	}
	delete[] p;
}



void wypelnijMacierz(int m, int n)
{
	int r, c;
	r=m;
	c=n;

	for (int i = 0; i < c; i++)
		for (int j = 0; j < r; j++) object.setv(i, j, 0.1 + rand() % 2);
}



int lkolumn(int m)
{
	if (m < 0 )
	{
		return -1;
	}

	return m;// zwraca liczbe kolumn


}
int lwierszy(int n)
{

	if (n < 0)
	{
		return -1;
	}

	return n ;// zwraca liczbe wierszy


}

//funkcja wyswietlajaca J
void wypiszMacierz(int m, int n)
{
	for (int i = 0; i < m; i++)
	{
		for (int j = 0; j < n; j++)
		{
			cout << p[m][n] << "  " << endl;
		}
	}
}
Zmien rozmiar(){
...}

2

Okej, podstawa: to klasa Macierz ma zarządzać swoją pamięcią, a nie Ty na zewnątrz. Więc powinnaś zrobić to w konstruktorze.

Przydatne linki:

Najlepiej zacznij od napisania pustej klasy Macierz, wyłącznie z konstruktorem i destruktorem. I potem do niej dopisuj kolejne funkcjonalności.

2
  1. Konstruktor kopiujący powinien skopiować także zawartość macierzy oryginalnej.
  2. lkomumn, lwierszy to zdecydowanie metody klasy (funkcje w klasie), a nie zwykłe funkcje. Tak samo zmiana rozmiaru macierzy. Przyjąłbym zasadę, iż funkcje zapewniające podstawowe operacje na macierzy powinny być częścią klasy. Funkcję operujące na macierzy przeniósłbym poza klasę tylko wtedy, jeżeli koncepcyjnie by nie pasowała do reszty metod i dałoby się ją zaimplementować z użyciem innych metod wystawionych przez klasę, ewentualnie jeżeli język wymaga, by była zdefiniowana poza klasą.
  3. Wypisywanie zaimplementowałbym z użyciem strumieni (tzn. poprzez przeciązenie operatora <<)
  4. Przeczytaj to co podlinkował @kq . Na jego blogu znajdziesz mnóstwo pożytecznych informacji.
1

Może taki wzorzec na początek (Pisane na kolanie, mogą być drobne problemy.):

class Matrix
{
	private:
	size_t rows,cols;
	double **m; // rezeczywiste
	public:
	Matrix():rows(0),cols(0),m(nullptr) {}
	Matrix(size_t rows,size_t cols):rows(rows),cols(cols),m(alloc()) {}
	Matrix(const Matrix &m):rows(m.rows),cols(m.cols),m(alloc()) { copy(m.m); }
	~Matrix() { free(); }
	Matrix &operator=(const Matrix &m) { /* do zrobienia */ }
	double &cell(size_t r,size_t c) { return m[r][c]; }
	double cell(size_t r,size_t c)const { return m[r][c]; }
	friend ostream &operator<<(ostream &s,const Matrix &m) { return m.prn(s); }
	private:
	double **alloc();
	void copy(const double **src);
	void free();
	ostream &prn(ostream &s)const
};

double **Matrix::alloc()
{
 	double **tmp=new double*[rows];
	for(int r=0;r<rows;++r) tmp[r]=new double[cols];
	return tmp;
}

void Matrix::copy(const double **tmp)
{
	for(int r=0;r<rows;++r) for(int c=0;c<cols;++c) m[r][c]=tmp[r][c];
}

void Matrix::free()
{
	for(int r=0;r<rows;++r) delete[] tmp[i];
	delete[] tmp;
}

ostream &Matrix::prn(ostream &s)const
{
	s.setf(ios::fixed);
	for(int r=0;r<rows;++r,s<<endl)
	{
		for(int c=0;c<cols;++c) s<<setw(9)<<setprecision(2)<<m[r][c]<<' ';
	}
	return s;
}
4

Prawda jest taka, że "nauczyciele" z uporem maniaka, powtarzają wzorce nauczania C++ z lat 90.
I nie mówię tu tylko o C++11 (std::vector był już w C++98 - jak nie wcześniej).
Ręczne zarządzanie pamięcią w C++ nie jest trudne, ale pełne pułapek. W uczniowskim kodzie to nie ma to sensu (po co ucznia maltretować czymś, czego mało kto potrzebuje), zwłaszcza że w profesjonalnym kodzie nikt tego już nie robi (poza jakimiś ekstremalnymi przypadkami mikrooptymalizacji),

0
MarekR22 napisał(a):

Ręczne zarządzanie pamięcią w C++ nie jest trudne, ale pełne pułapek. W uczniowskim kodzie to nie ma to sensu (po co ucznia maltretować czymś, czego mało kto potrzebuje), zwłaszcza że w profesjonalnym kodzie nikt tego już nie robi (poza jakimiś ekstremalnymi przypadkami mikrooptymalizacji),

Prawie się zgadzam, ale... :) Celem tego "maltretowania" nie jest nauczenie czegoś, czego mało potrzebuje, ale nauczenie, jak działa komputer na niskim poziomie. Oczywiście:

  1. powinno iść to w parze z pokazaniem mechanizmów wyższego poziomu i ich przewagi oraz zachęceniem do ich używania;
  2. sensownym wyjaśnieniem ogólnego działania maszyny na niskim poziomie.

C (i C++) są do tego dobrymi językami, tylko często źle używanymi w dydaktyce (mówię oczywiście o poziomie klasy informatycznej w liceum/technikum czy początku studiów informatycznych).

0

Po doczytaniu, dooglądaniu i doradzeniu się, z mojego kodu powstało coś takiego ale nie jest to wciąż coś co działa ;/
Ogólnie program jest jeszcze zmodyfikowany ponieważ połączony z kolejnym zadaniem które polegało na przeciążeniu operatorów.
Stanęłam w miejscu.

#ifndef HEADER_H
#define HEADER_H
using namespace std;
class Macierz {
public:
    float** matrix; 							// tab dwuwymiarowa
    int m;
    int n;
    Macierz(); 									// Konstr domyslny
    Macierz(const int m, const int n); 			// Konstrukt tworzacy macierz o zadanych rozmiarach
    Macierz(float** matrix, int n, int m); 		// Konstr twarzacy macierz na podstawie tab przekazanej jako arg
    Macierz(const Macierz& matrix); 		// Konstr kopiujacy
    ~Macierz();      							// Destruktor
    void changeDims(int m, int n); 				// Funkcja mieniajaca rozmiar pamieci
    int lcols(); 							// Fun zwaracaca ilosc kolumn
    int lrows(); 							// Fun zwracajaca ilosc wierszy
    void generateMacierz(); 						// fun generuja macierz z przecialu 0.0 do 1.0
    void printMacierz(); 							// fun wypisujaca macierz na ekranie


    Macierz& operator=(const Macierz& other);
    Macierz operator+(const Macierz& matrix);
    Macierz operator-(const Macierz& matrix);
    Macierz operator*(const float n);
    Macierz operator*(const Macierz& matrix);
    Macierz& operator*=(const float n);
    Macierz& operator*=(const Macierz& matrix);
    Macierz& operator+=(const Macierz& matrix);
    Macierz& operator-=(const Macierz& matrix);
    bool operator==(const Macierz& other);
    bool operator!=(const Macierz& other);
    float* operator[](int n);
    float operator()(int m, int n);
    friend std::ostream& operator<<(std::ostream& os, const Macierz& matrix);
    friend std::istream& operator>>(std::istream& is, const Macierz& matrix);
};

Macierz operator+(const Macierz& matrix1, const Macierz& matrix2) {
    Macierz outMacierz(matrix1.m, matrix1.n);
    for (int i = 0; i < matrix1.m; i++) {
        for (int j = 0; matrix1.n; j++) {
            outMacierz.matrix[i][j] = matrix1.matrix[i][j] + matrix1.matrix[i][j];
        }
    }
    return outMacierz;
}

Macierz operator-(const Macierz& matrix1, const Macierz& matrix2) {
    Macierz outMacierz(matrix1.m, matrix1.n);
    for (int i = 0; i < matrix1.m; i++) {
        for (int j = 0; matrix1.n; j++) {
            outMacierz.matrix[i][j] = matrix1.matrix[i][j] - matrix1.matrix[i][j];
        }
    }
    return outMacierz;
}

#endif
___________________________________________________________
#include "header.h"
#include <iostream>
using namespace std;


//Domyslny konstruktor 
Macierz::Macierz() : Macierz(0, 0) {}

// Konstruktor tworzacy macierz o zadnych rozmiarach
Macierz::Macierz(const int m, const int n) { 
    this->m = m;
    this->n = n;
    this->matrix = (float**)malloc(m * sizeof(float*));
    for (int i = 0; i < m; i++) {
        this->matrix[i] = (float*)malloc(n * sizeof(float));
    }
}

// Konstr twarzacy macierz na podstawie tab przekazanej jako arg
Macierz::Macierz(float** matrix, int m, int n) { 
    this->m = m;
    this->n = n;
    this->matrix = (float**)malloc(m * sizeof(float*));
    for (int i = 0; i < m; i++) {
        this->matrix[i] = (float*)malloc(n * sizeof(float));
    }
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            this->matrix[i][j] = matrix[i][j];
        }
    }
}
Macierz::Macierz(const  Macierz& matrix)
{
}
// Konstr kopiujacy
Macierz::Macierz(const Macierz& obj) { 
    this->m = obj.m;
    this->n = obj.n;
    this->matrix = (float**)malloc(m * sizeof(float*));
    for (int i = 0; i < m; i++) {
        this->matrix[i] = (float*)malloc(n * sizeof(float));
    }
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            this->matrix[i][j] = obj.matrix[i][j];
        }
    }
}
// Destruktor
Macierz::~Macierz() { 
    for (int i = 0; i < this->m; i++) {
        delete[] this->matrix[i];
    }
    delete[] this->matrix;
}
// Fun zwaracaca ilosc kolumn
int Macierz::lcols() { 
    return this->m;
}
// Fun zwracajaca ilosc wierszy
int Macierz::lrows() {  
    return this->n;
}

// Funkcja mieniajaca rozmiar pamieci
void Macierz::changeDims(int m, int n) { 
    this->m = m;
    this->n = n;
    this->matrix = (float**)realloc(this->matrix, m * sizeof(float*));
    for (int i = 0; i < m; i++) {
        if (this->matrix[i] != nullptr) this->matrix[i] = (float*)realloc(this->matrix[i], n * sizeof(float));
        else this->matrix[i] = (float*)malloc(n * sizeof(float));
    }
}
// fun generuja macierz z przecialu 0.0 do 1.0
void Macierz::generateMacierz() { 
    srand(time(NULL));
    for (int i = 0; i < this->m; i++) {
        for (int j = 0; j < this->n; j++) {
            this->matrix[i][j] = static_cast <float> (rand()) / static_cast <float> (RAND_MAX);
        } // STATIC_CAST < NAZWA TYPTU> (WYRAZENIE)
    }
}
// fun wypisujaca macierz na ekranie
void Macierz::printMacierz() {  
    for (int i = 0; i < this->m; i++) {
        for (int j = 0; j < this->n; j++) {
            std::cout << this->matrix[i][j] << " ";
        }
        std::cout << endl;
    }
}
// poprawić
Macierz& Macierz::operator=(const Macierz& other) {
    if (this == &other) return *this;
    for (int i = 0; i < this->m; i++) {
        for (int j = 0; j < this->n; j++) {
            this->matrix[i][j] = other.matrix[i][j];
        }
    }
    return *this;
}

Macierz Macierz::operator+(const Macierz& matrix) {
    Macierz outMacierz(this->m, this->n);
    for (int i = 0; i < this->m; i++) {
        for (int j = 0; j < this->n; j++) {
            outMacierz.matrix[i][j] = this->matrix[i][j] + matrix.matrix[i][j];
        }
    }
    return outMacierz;
}

Macierz Macierz::operator-(const Macierz& matrix) {
    Macierz outMacierz(this->m, this->n);
    for (int i = 0; i < this->m; i++) {
        for (int j = 0; j < this->n; j++) {
            outMacierz.matrix[i][j] = this->matrix[i][j] - matrix.matrix[i][j];
        }
    }
    return outMacierz;
}

Macierz Macierz::operator*(const float n) {
    Macierz outMacierz(this->m, this->n);
    for (int i = 0; i < this->m; i++) {
        for (int j = 0; j < this->n; j++) {
            outMacierz.matrix[i][j] = this->matrix[i][j] * n;
        }
    }
    return outMacierz;
}

Macierz Macierz::operator*(const Macierz& other) {
    Macierz outMacierz(this->m, other.n);
    for (int i = 0; i < this->m; i++) {
        for (int j = 0; j < this->n; j++) {
            outMacierz[i][j] = 0;
            for (int k = 0; k < other.m; k++) {
                outMacierz[i][j] += this->matrix[i][k] * other.matrix[k][j];
            }
        }
    }
    return outMacierz;
}

Macierz& Macierz::operator*=(const Macierz& other) {
    for (int i = 0; i < this->m; i++) {
        for (int j = 0; j < this->n; j++) {
            this->matrix[i][j] *= other.matrix[i][j];
        }
    }
    return *this;
}

Macierz& Macierz::operator+=(const Macierz& matrix) {
    for (int i = 0; i < this->m; i++) {
        for (int j = 0; j < this->n; j++) {
            this->matrix[i][j] += matrix.matrix[i][j];
        }
    }
    return *this;
}

Macierz& Macierz::operator-=(const Macierz& matrix) {
    for (int i = 0; i < this->m; i++) {
        for (int j = 0; j < this->n; j++) {
            this->matrix[i][j] -= matrix.matrix[i][j];
        }
    }
    return *this;
}

Macierz& Macierz::operator*=(const float n) {
    for (int i = 0; i < this->m; i++) {
        for (int j = 0; j < this->n; j++) {
            this->matrix[i][j] *= n;
        }
    }
    return *this;
}

bool Macierz::operator==(const Macierz& other) {
    if (this->m != other.m || this->n != other.n) return false;
    for (int i = 0; i < this->m; i++) {
        for (int j = 0; j < this->n; j++) {
            if (this->matrix[i][j] != other.matrix[i][j]) return false;
        }
    }
    return true;
}

bool Macierz::operator!=(const Macierz& other) {
    if (this->m != other.m || this->n != other.n) return true;
    for (int i = 0; i < this->m; i++) {
        for (int j = 0; this->n; j++) {
            if (this->matrix[i][j] != other.matrix[i][j]) return true;
        }
    }
    return false;
}

std::ostream& operator<<(std::ostream& os, const Macierz& matrix) {
    for (int i = 0; i < matrix.m; i++) {
        for (int j = 0; j < matrix.n; j++) {
            std::cout << matrix.matrix[i][j] << " ";
        }
        std::cout << endl;
    }
    return os;
}

std::istream& operator>>(std::istream& is, const Macierz& matrix) {
    for (int i = 0; i < matrix.m; i++) {
        for (int j = 0; j < matrix.n; j++) {
            is >> matrix.matrix[i][j];
        }
    }
    return is;
}

float* Macierz::operator[](int n) {
    if (n < 0 || n >= this->m) return nullptr;
    return this->matrix[n];
}

float Macierz::operator()(int m, int n) {
    if (m < 0 || m >= this->m || n < 0 || n >= this->n) return FLT_MAX;
    return this->matrix[m][n];
}
__________________________________________________________
#include <iostream>
#include <stdlib.h>
#include <time.h>
#include <float.h>
#include <string>
#include "header.h"
using namespace std;



int main() {
    int m = 2;
    int n = 2;
    float** matrix = (float**)malloc(m * sizeof(float*));
    for (int i = 0; i < m; i++) {
        matrix[i] = (float*)malloc(n * sizeof(float));
    }
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            matrix[i][j] = 10;

        }
    }

    Macierz m1(m, n);
    m1.generateMacierz();
    Macierz m2(matrix, m, n);
    Macierz m3(m1);

    std::cout << " Macierz m1\n" << m1 << std::endl;
    std::cout << " Macierz m2\n" << m2 << std::endl;
    std::cout << " Macierz m3\n" << m3 << std::endl;


    std::cout << "Kolumny: " << m1.lcols() << std::endl;
    std::cout << "Wiersze: " << m1.lrows() << std::endl << std::endl;
    std::cout << " Macierz m1" << std::endl;
    m1.printMacierz();
    std::cout << std::endl;

    Macierz m5(2, 2);
    m5 = m1;
    std::cout << " m5\n" << m5 << std::endl;

    std::cout << " m2+m1\n" << m2 + m1 << std::endl;
    std::cout << " m2-m1\n" << m2 - m1 << std::endl;

    std::cout << " m1*5\n" << m1 * 5 << std::endl;
    std::cout << " m2*m2\n" << m2 * m2 << std::endl;

    m1 += m2;
    std::cout << " m1+=m2\n" << m1 << std::endl;
    m1 -= m2;
    std::cout << " m1-=m2\n" << m1 << std::endl;

    bool are_equal = (m1 == m2);
    std::cout << " m1 i m2 sa rowne:\n" << are_equal << std::endl;

    bool are_not_equal = (m1 != m2);
    std::cout << "\n m1 i m2 nie sa rowne: \n" << are_not_equal << std::endl;

    std::cout << "\n m2[1][1]\n" << m2[1][1] << std::endl;
    std::cout << "\n m2(1,1)\n" << m2(1, 1) << std::endl;

    Macierz m6(2, 2);
    std::cout << "\nWpisz macierz 6: ";
    std::cin >> m6;
    std::cout << m6;
}

0

operator= skopany, czemu uważasz że kopiowana tablica będzie mieć ten sam rozmiar?

Skoro już przydzielasz malloc'kiem, to:
to można co nieco uprościć.
Np konstruktor.

Macierz::Macierz(int rows,int cols):rows(rows),cols(cols),matrix((float**)malloc(rows*sizeof(float*)))
{ 
    float *tmp=(float*)malloc(rows*cols*sizeof(float));
    for(int r=0;r<rows;++r,tmp+=cols) this->matrix[r]=tmp;
}

zauważ że teraz kopiowanie odbywa da się zrobić jednym memcpy

m,n, j,i która para jest wysokością która szerokościa? Prosisz się o zbędny godziny szukania błędów na własne życzenie.

1 użytkowników online, w tym zalogowanych: 0, gości: 1