Visualizzazione dei risultati da 1 a 7 su 7
  1. #1
    Utente di HTML.it
    Registrato dal
    Apr 2009
    Messaggi
    59

    [C++] Classe matrice

    Ciao a tutti!!

    Stavo facendo un esercizio in c++, ho completato tutto, però vorrei un vostro parere.
    Questo è il codice:

    Interfaccia
    codice:
    #ifndef MATRICE_H
    #define MATRICE_H
    
    typedef double tipoElem; 
    
    class Matrice {
    private:
    	int righe;
        int colonne;
        tipoElem **elementi;
    public:
        Matrice(int r, int c); 
    	Matrice(const Matrice& mat); 
    	int GetRighe();
    	int GetColonne();
    	void StampaMatrice(); 
    	void AzzeraMatrice(); 
        tipoElem LeggiMatrice(int r, int c);
        void ScriviMatrice(int r, int c, tipoElem val);
    	void ProdottoScalare(double scalare); 
    	Matrice Trasposta(); 
    	Matrice ProdottoMatriciale(Matrice m2); 
    };
    
    #endif
    Implementazione
    codice:
    #include "Matrice.h"
    #include <iostream>
    
    using namespace std; 
    
    Matrice::Matrice(int r, int c)
    {
    	colonne = c;
    	righe = r;
    
    	int i;
    	elementi = new tipoElem* [righe];
    	for (i = 0; i < righe; i++)
    		elementi[i] = new tipoElem[colonne];
    
    	AzzeraMatrice(); 
    }
    
    Matrice::Matrice(const Matrice& matCopy)
    {
    	righe = matCopy.righe;
    	colonne = matCopy.colonne; 
    	
    	elementi = new double*[righe]; 
    	for(int i = 0; i < righe; i++)
    	{
    		elementi[i] = new double[colonne]; 
    	}
    
    	for(int i = 0; i < righe; i++)
    	{
    		for(int j = 0; j < colonne; j++)
    		{
    			elementi[i][j] = matCopy.elementi[i][j]; 
    		}
    	}
    }
    
    int Matrice::GetRighe()
    {
    	return righe; 
    }
    
    int Matrice::GetColonne()
    {
    	return colonne; 
    }
    
    void Matrice::StampaMatrice()
    {
    	for(int i = 0; i < righe; i++)
    	{
    		for(int j = 0; j < colonne; j++)
    		{
    			cout << LeggiMatrice(i, j) << " "; 
    		}
    		cout << endl; 
    	}
    }
    
    void Matrice::AzzeraMatrice()
    {
    	for(int i = 0; i < righe; i++)
    	{
    		for(int j = 0; j < colonne; j++)
    		{
    			ScriviMatrice(i, j, 0); 
    		}
    	}
    }
    
    tipoElem Matrice::LeggiMatrice(int r, int c)
    {
    	try
    	{
    		if(r >= 0 && r < righe && c >= 0 && c < colonne)
    		{
    			return elementi[r][c]; 
    		}
    		else
    		{
    			throw "Indici errati."; 
    		}
    	}
    	catch(char *string)
    	{
    		cout << endl << string << endl; 
    	}
    }
    
    void Matrice::ScriviMatrice(int r, int c, tipoElem val)
    {
    	try
    	{
    		if(r >= 0 && r < righe && c >= 0 && c < colonne)
    		{
    			elementi[r][c] = val; 
    		}
    		else
    		{
    			throw "Indici errati."; 
    		}
    	}
    	catch(char *string)
    	{
    		cout << endl << string << endl; 
    	}
    }
    
    void Matrice::ProdottoScalare(double scalare)
    {
    	for(int i = 0; i < righe; i++)
    	{
    		for(int j = 0; j < colonne; j++)
    		{
    			ScriviMatrice(i, j, LeggiMatrice(i, j) * scalare); 
    		}
    	}
    }
    
    Matrice Matrice::Trasposta()
    {
    	Matrice trasposta(righe, colonne); 
    
    	for(int i = 0; i < righe; i++)
    	{
    		for(int j = 0; j < colonne; j++)
    		{
    			trasposta.ScriviMatrice(i, j, LeggiMatrice(j, i)); 
    		}
    	}
    
    	return trasposta; 
    }
    
    Matrice Matrice::ProdottoMatriciale(Matrice m2)
    {
    	Matrice matProd(righe, m2.GetColonne()); 
    
    	for(int i = 0; i < righe; i++)
    	{
    		for(int j = 0; j < m2.GetColonne(); j++)
    		{
    			matProd.ScriviMatrice(i, j, 0); 
    			for(int k = 0; k < righe; k++)
    			{
    				matProd.ScriviMatrice(i, j, matProd.LeggiMatrice(i, j) + (LeggiMatrice(i, k) * m2.LeggiMatrice(k, j))); 
    			}
    		}
    	}
    
    	return matProd; 
    }
    Ora il mio dubbio sorge perché nei metodi Trasposta e ProdottoMatriciale faccio restituire la matrice che ottengo eseguendo i vari calcoli, per come ho fatto però mi viene da pensare che in realtà stia restituendo la matrice che verrà distrutta alla fine del metodo stesso.
    Quindi mi chiedevo se in realtà il metodo corretto era questo:

    codice:
    ...
    ...
    Matrice* Matrice::Trasposta()
    {
    	Matrice *trasposta = new Matrice(righe, colonne); 
    
    	for(int i = 0; i < righe; i++)
    	{
    		for(int j = 0; j < colonne; j++)
    		{
    			trasposta->ScriviMatrice(i, j, LeggiMatrice(j, i)); 
    		}
    	}
    
    	return trasposta; 
    }
    
    Matrice* Matrice::ProdottoMatriciale(Matrice m2)
    {
    	Matrice *matProd = new Matrice(righe, m2.GetColonne()); 
    
    	for(int i = 0; i < righe; i++)
    	{
    		for(int j = 0; j < m2.GetColonne(); j++)
    		{
    			matProd->ScriviMatrice(i, j, 0); 
    			for(int k = 0; k < righe; k++)
    			{
    				matProd->ScriviMatrice(i, j, matProd->LeggiMatrice(i, j) + (LeggiMatrice(i, k) * m2.LeggiMatrice(k, j))); 
    			}
    		}
    	}
    
    	return matProd; 
    }
    Grazie a tutti anticipatamente

  2. #2
    Utente di HTML.it L'avatar di shodan
    Registrato dal
    Jun 2001
    Messaggi
    2,381
    In una classe container come questa è corretto restituire oggetti per valore.
    Il vero problema è che non hai implementato un operatore di assegnamento.
    Per tua fortuna non hai nemmeno implementato il distruttore (errore da penna blu, credo), per cui perdi un pò di memoria in giro ma non hai crash inspiegabili.

    Per inciso una classe simile è un buon esercizio per vedere da vicino le problematiche di una classe container. Tipo: se passo -1 o 0 al costruttore che succede?
    This code and information is provided "as is" without warranty of any kind, either expressed
    or implied, including but not limited to the implied warranties of merchantability and/or
    fitness for a particular purpose.

  3. #3
    Utente di HTML.it
    Registrato dal
    Apr 2009
    Messaggi
    59
    ARRR il distruttore me lo ero proprio dimenticato comunque l'ho impostato in questa maniera:

    codice:
    Matrice::~Matrice()
    {
    	for(int i = 0; i < righe; i++)
    	{
    		delete []elementi[i]; 
    	}
    
    	delete []elementi; 
    }
    Ho messo i controlli anche al costruttore

    Tuttavia non capisco perché hai detto questo:
    Il vero problema è che non hai implementato un operatore di assegnamento.
    Per tua fortuna non hai nemmeno implementato il distruttore (errore da penna blu, credo), per cui perdi un pò di memoria in giro ma non hai crash inspiegabili.
    o meglio capisco il discorso del distruttore, però cosa c'entra l'operatore assegnamento? Non l'ho mai usato, perché dovrebbe creare problemi non averlo già previsto?

    Comunque voglio precisare che la classe non è ancora finita...

    Come ultima cosa, se vuoi, puoi spiegarmi meglio perché

    In una classe container come questa è corretto restituire oggetti per valore.
    Grazie mille per la risposta

  4. #4
    Utente di HTML.it L'avatar di shodan
    Registrato dal
    Jun 2001
    Messaggi
    2,381
    Originariamente inviato da premoli
    o meglio capisco il discorso del distruttore, però cosa c'entra l'operatore assegnamento? Non l'ho mai usato, perché dovrebbe creare problemi non averlo già previsto?
    Perché restituiendo una copia per valore, e non avendo l'operatore di assegnamento, il compilatore creerà una copia bit a bit della variabile matrice locale. Quindi avrai due variabili identiche che distruggeranno il medesimo puntatore, con inevitabile crash (più o meno colonne + 1 crash).
    Caso tipico (visto che non c'è costruttore di default).
    codice:
    Matrice a(10,20);
    Matrice b(4,5);
    a = b;
    *bum*
    Quando hai un puntatore in una classe che decidi di gestirlo in proprio: costruttore di copia, operatore di assegnamento e distruttore sono obbligatori. Sempre.

    Come ultima cosa, se vuoi, puoi spiegarmi meglio perché...
    Se devi restituire una matrice contenente dati elaborati, restituisci una matrice non un puntatore a matrice. Come in una ipotetica funzione int add(int,int) restituisci un int, non un int*.
    This code and information is provided "as is" without warranty of any kind, either expressed
    or implied, including but not limited to the implied warranties of merchantability and/or
    fitness for a particular purpose.

  5. #5
    Utente di HTML.it
    Registrato dal
    Apr 2009
    Messaggi
    59
    Ciao scusa se rispondo solo ora...

    Prima di tutto grazie...

    Infatti non avevo pensato al fatto dell'operatore di assegnamento, in effetti quando faccio ad esempio
    C = A.ProdottoMatriciale(B);

    il programma va in crash, se non ho capito male è lo stesso "problema" che si ha quando non si prevede il costruttore di copia, ovvero avrò due "entità" che puntano alla stessa area di memoria e conseguentemente quando verrà eliminata una l'altra non potrà più accedere alla suddetta area, giusto?

    grazie mille di nuovo...

  6. #6
    Utente di HTML.it L'avatar di shodan
    Registrato dal
    Jun 2001
    Messaggi
    2,381
    Si, il problema è lo stesso.
    This code and information is provided "as is" without warranty of any kind, either expressed
    or implied, including but not limited to the implied warranties of merchantability and/or
    fitness for a particular purpose.

  7. #7
    Utente di HTML.it
    Registrato dal
    Apr 2009
    Messaggi
    59
    Grazie mille, sei stato gentilissimo...

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2026 vBulletin Solutions, Inc. All rights reserved.