salve a tutti, mi chiamo leonardo e questo è il mio primo post su un forum di programmazione. ho un problema su un (piccolissimo e inutile) programma in c++, che si manifesta quando vado a dividere il tutto in tre file

mi spiego meglio... vorrei dividere il codice x formare un main, un file .h e un file .cpp... però quando vado a fare ciò il compilatore mi segnala un errore che io non so da dove venga... (cioè so da dove viene ma non so come fare -_-)

vi allego il codice, spero in qualche anima buona tra voi

codice:
#include <iostream>
#include <vector>

using namespace std;

typedef vector<int> riga;

// modello della classe matrix
class matrix: public vector<riga> {
//la riga precedente significa: la classe matrix estende l'oggetto vector<riga>, ereditandone le proprieta'.
//cio' permette di usare, dalla main, espressioni come: m1[3][2], perche' il doppio indice [][] e' supportato
//dal vector<riga> e quindi automaticamente viene ereditato dalla classe matrix.
	public:
		matrix(int,int,int,int,int,int,int,int,int);
		matrix();
		void setidentity();
		void print();
	
	friend ostream& operator<< (ostream&, const matrix&);
	friend matrix operator* (const int, const matrix&);
	//notare che il * per scalari con il numero a sinistra non puo' essere overloadato
	//alla maniera "funzioni membro", cosi' come il << (quest'ultimo perche' non siamo noi
	//ad avere scritto la classe ostream!)

	//in questo esempio si approccia l'overloading (dove possibile) mediante funzioni membro...
	//una cosa come:
	//	m1 + m2;
	//viene vista come:
	// m1.operator+(m2);

	matrix operator+ (const matrix&);
	matrix& operator+= (const matrix&);
	matrix operator* (const matrix&);
	matrix operator* (int) const;
	bool operator== (const matrix&);
};

// codice della classe matrix
matrix::matrix(){
	// costruttore di default: tutti gli elementi a zero.
	int i,j;
	riga riga_temp;
	for (i=0;i<=2;i++){
		for(j=0;j<3;j++){
			riga_temp.push_back(0);
		}
		push_back(riga_temp);
	}
}

matrix::matrix(int a11, int a12, int a13, int a21, int a22, int a23, int a31, int a32, int a33){
	// costruttore con valori dati nella dichiarazione
		riga riga1;
		riga1.push_back(a11);
		riga1.push_back(a12);
		riga1.push_back(a13);
		riga riga2;
		riga2.push_back(a21);
		riga2.push_back(a22);
		riga2.push_back(a23);
		riga riga3;
		riga3.push_back(a31);
		riga3.push_back(a32);
		riga3.push_back(a33);
		push_back(riga1);
		push_back(riga2);
		push_back(riga3);
}

void matrix::setidentity(){
	// imposta la matrice all'identita' 3x3
	int i,j;
	for (i=0;i<=2;i++){
		for (j=0;j<=2;j++){
			(*this)[i][j]=(i==j?1:0);	
			// questo e' un delta di Kronecker
		}
	}
}

void matrix::print(){
	// stampa in forma matriciale (righe e colonne: vedi l'uso di endl e di "\t")
	int i,j;
	for (i=0;i<=2;i++){
		for (j=0;j<=2;j++){
			cout << (*this)[i][j] << "\t";
		}
		cout << endl;
	}
}

//overloading degli operatori:

ostream& operator<< (ostream& os, const matrix& m){
	// vedi print()
	int i,j;	
	for (i=0;i<=2;i++){
		for (j=0;j<=2;j++){
			os << m[i][j] << "\t";
		}
		os << endl;
	}
	// viene ritornato un *riferimento* allo stesso oggetto os che e' passato, senza farne
	// una copia nuova (infatti il tipo di dato di ritorno e' ostream& e non ostream!)
	return os;
}

matrix matrix::operator+ (const matrix& m2){
	// anche se la funzione non modifica i valori di m1 e m2, e sarebbe indifferente
	// dichiarare parametri matrix o matrix&, per evitare la creazione di due nuovi oggetti
	// si preferisce usare la & (risparmiando le risorse necessarie per la copia).
	// L'uso di "const" serve ad evitare che la funzione (mal scritta) sia in grado di
	// modificare gli argomenti: il compilatore darebbe un errore.

	// somma elemento per elemento
	int i,j; // indici del risultato...
	matrix sum;
	for (i=0;i<=2;i++){
		for (j=0;j<=2;j++){
			// elemento (i,j) della somma:
			sum[i][j]=(*this)[i][j]+m2[i][j];
		}
	}
	// viene ritornato un *nuovo* oggetto di tipo matrix! (non c'e' & dopo matrix nel tipo
	// di ritorno)
	return sum;
}

matrix& matrix::operator+= (const matrix& m_source){
	// ecco un caso in cui m_source non viene modificata (ed e' const), mentre i valori di
	// m_dest vanno modificati, e non si usa la parola chiave const. Inoltre, la funzione
	// in se' rende a sua volta un riferimento a m_dest per permettere espressioni come:
	//	m3 = (m2+=m1);
	// Il valore di ritorno non viene usato da istruzioni come:
	//	m5+=m4;
	// appoggiandosi all'operatore +, gia' overloadato, basta scrivere:
	(*this) = (*this) + m_source;
	return (*this);
}

matrix matrix::operator* (const matrix& m2){
	//prodotto tra matrici: la formula richiede l'uso di tre indici...
	int i,j; // indici del risultato...
	int k; // questo per il calcolo dell'elemento della matrice prodotto
	int temp;
	matrix prod;
	for (i=0;i<=2;i++){
		for (j=0;j<=2;j++){
			// elemento (i,j) del prodotto:
			temp=0;
			for (k=0;k<=2;k++){
				temp+=(*this)[i][k]*m2[k][j];
			}
			prod[i][j]=temp;
		}
	}
	return prod;
}

matrix operator* (int number, const matrix& m2){
	return m2 * number;
}

matrix matrix::operator* (const int number) const{
	// prodotto per scalari
	// come per il costructor, possono convivere piu' funzioni con lo stesso nome,
	// con identico tipo di dato di ritorno, ma diversi argomenti: il compilatore
	// si occupera' di chiamare di volta in volta la corretta versione della funzione;
	// cosi' e' risolta l'ambiguita' tra (matrix)*(matrix) e (int)*(matrix), ovvero
	// tra prodotto tra matrici e per scalari.
	int i,j; // indici del risultato...
	matrix scalar_prod;
	for (i=0;i<=2;i++){
		for (j=0;j<=2;j++){
			scalar_prod[i][j]=(*this)[i][j]*number;
		}
	}
	return scalar_prod;
}

bool matrix::operator== (const matrix& m2){

	//serve ad estendere l'operatore == ad oggetti matrix, rendendo vero
	// se e solo se gli elementi coincidono uno ad uno.

	bool sofar = true;
	int i,j;
	for (i=0;i<=2;i++){
		for (j=0;j<=2;j++){
			if ((*this)[i][j] != m2[i][j]) sofar = false;
		}
	}
	return sofar;
}

/****************************************************************************************
*											*
*				FINE CLASSE - INIZIO MAIN DI ESEMPIO			*
*											*
*****************************************************************************************/


int main(){
	matrix m1;
	matrix m2(1,2,3,4,5,6,7,8,9);
	cout << "-> Stampa m2:\n";
	m2.print();
	cout << "\n-> Stampa m1:\n";
	m1.print();
	cout << "\n\n-> Stampa dell'elemento (2,2) di m2 con m2[2][2]:\n";
	cout << m2[2][2];
	cout << "\n\n-> SetIdentity e stampa di m1:\n";
	m1.setidentity();
	m1.print();
	cout << "\n\n-> Set di un -1 in (1,1):\n";
	m1[1][1]=-1;
	m1.print();

	cout << "\n\n-> Stampa con << di m2...\n" << m2 << endl;

	matrix m3 = m1 + m2;
	cout << "\n\n-> Somma di m1 e m2 = m3:\n";
	m3.print();
	
	m3+=m2;
	cout << "\n\n-> Risultato di m3+=m2: m3 =\n";
	cout << m3 << endl;

	matrix m4 = m3 * m2;
	cout << "\n\n-> Prodotto di m3 e m2 = m4:\n";
	m4.print();

	matrix m5 = -2 * m4;
	cout << "\n\n-> Prodotto di -2 e m4 (per scalari):\n";
	m5.print();

	cout << "\n\n-> Confronti: (m1==m2) da': " << (m1==m2) << endl
	     << "-> invece (m2==m2) da': " << (m2==m2) << endl;
	
	cout << "\n=> Grazie per avere utilizzato questo divertente programma.\n";
	system ("PAUSE");
	return 0;

}
ciao a tutti e grazie comunque