Help with problem with overloading ostream operator for matrix class

Here is my matrix.h file
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#pragma once

#include <iostream>
using namespace std;
#ifndef MATRIX
#define MATRIX

typedef double ElementType;
class Matrix
{
	//friend ostream & operator<< (ostream & out, const Matrix & aMatrix);
public:
	Matrix(void);
	Matrix(int rows, int cols);
	Matrix(const Matrix & original); //copy constructor 
	~Matrix(void);
	
	void display (std::ostream & out) const;
	double get_element(int row, int col);
	void set_element(int row, int col, double new_value);

	int num_rows();
	int num_cols();
	Matrix transpose();
	Matrix &operator =(const Matrix & aMatrix);
	Matrix operator* (double scalar); 
	Matrix operator* (Matrix & matrixB);
	
private:
	int row_num;
	int col_num;
	double ** mydata;

};
//ostream & operator<< (ostream & out, Matrix & aList);
ostream & operator<< (ostream & out, Matrix & aMatrix);

//Matrix &operator =(const Matrix & aMatrix);

#endif 

Matrix.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#include "Matrix.h"
#include <cassert>
#include <iomanip>
#include <iostream>
using namespace std;

Matrix::Matrix(void)
	:row_num(20), col_num(20)
{
	mydata = new double * [row_num];
	for (int x = 0; x < row_num; x++)
		mydata[x] = new double [col_num];
	for (int i = 0; i < row_num; i++)
		for (int j = 0; j < col_num; j++)
			mydata[i][j] = 0.0;
}

Matrix::Matrix(int rows, int cols)
	:row_num(rows), col_num(cols)
{
	mydata = new double * [row_num];
	for (int x = 0; x < row_num; x++)
		mydata[x] = new double [col_num];
	for (int i = 0; i < row_num; i++)
		for (int j = 0; j < col_num; j++)
			mydata[i][j] = 0.0;
}

Matrix::~Matrix(void)
{
	for (int i = 0; i < row_num; i++)
		delete [] mydata[i];
	delete [] mydata;
}

Matrix::Matrix(const Matrix & original) //copy constructor
	:row_num(original.row_num), col_num(original.col_num)
{
	mydata = new double * [row_num];
	for (int x = 0; x < row_num; x++)
		mydata[x] = new double [col_num];
	for (int i = 0; i < row_num; i++)
		for (int j = 0; j < col_num; j++)
			mydata[i][j] = original.mydata[i][j];

}


int Matrix::num_rows()
{
	return row_num; 
}
int Matrix::num_cols()
{
	return col_num;
}

void Matrix::display(ostream & out) const
{
}

ostream & operator<< (ostream & out, Matrix & aMatrix)
{
		if (aMatrix.num_rows() == 0 || aMatrix.num_cols() == 0)
	{
		out<<"Invalid Matrx";
	}
	else
	{

	for (int i = 0; i < aMatrix.num_rows(); i++)
	{
		for (int j = 0; j < aMatrix.num_cols(); j++)
			out << setw(7) << aMatrix.get_element(i, j);
		out << endl;
	}
	}

	return out;
}

Matrix Matrix::operator* (double scalar) 
{
	Matrix newMatrix(this->num_rows(), this->num_cols());
	for (int i = 0; i < this->num_rows(); i++)
		for (int j = 0; j < this->num_cols(); j++)
			newMatrix.set_element(i, j, this->get_element(i,j) * scalar);
	return newMatrix;
}

Matrix Matrix::operator* (Matrix & matrixB)
{
	if (this->num_cols() != matrixB.num_rows())
	{
		cout << "Matrices are not compatible for multiplication \n";
		return Matrix(0,0);
	}
	Matrix newMatrix(this->num_rows(), matrixB.num_cols());
	double temp = 0;
	for (int i = 0; i < newMatrix.num_rows(); i++)
	{
		for (int j = 0; j < newMatrix.num_cols(); j++)
		{
			for (int k = 0; k < this->num_cols(); k++)
			{
				temp += this->get_element(i,k) * matrixB.get_element(k,j);
			}
			newMatrix.set_element(i, j, temp);
			temp = 0;
		}
	}
	return newMatrix;
}

Matrix & Matrix::operator =(const Matrix & aMatrix)
{
	if (this == &aMatrix)//avoids self-assignment
	{
		return *this;
	}
	row_num = aMatrix.row_num;
	col_num = aMatrix.col_num;
	for (int i = 0; i < row_num; i++)
		for (int j = 0; j < col_num; j++)
			mydata[i][j] = aMatrix.mydata[i][j];
	return *this;
}

double Matrix::get_element(int row, int col)
{
	return mydata[row][col];
}

void Matrix::set_element(int row, int col, double new_value)
{
	mydata[row][col] = new_value;
}

Matrix Matrix::transpose()
{
	int rows = row_num;
	int cols = col_num;
	Matrix transposedMatrix(cols, rows); //creates a new matrix with row and col number switched
	for (int i = 0; i < rows; i++)
		for (int j = 0; j < cols; j++)
			set_element(j, i, mydata [i][j]);
	return transposedMatrix;
}

test.cpp (given by professor)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
//--- Program to test Matrix class.

#include <iostream>
using namespace std;

#include "Matrix.h"

int main()
{
    
    int i, j ;
    int rows, cols;
    
    // Test1: the default class constructor
    Matrix bigMatrix;
    cout << "Test 1: bigMatrix = \n" << bigMatrix;
    
    // Test2: the other class constructor
    Matrix dMatrix(4,5);
     
    rows = dMatrix.num_rows();
    cols = dMatrix.num_cols();
    
    // put some numbers into the matrix 
    for (i = 0; i < rows; i++) {
        for (j = 0; j < cols; j++)
            //if(i == j)
                dMatrix.set_element(i, j, i*1.0 + j*0.1);
    }
    
    cout << "\nTest 2: dMatrix = \n" << dMatrix;
    
    // get_element 
    cout << "\nTest 3: dMatrix[2][3] = " << dMatrix.get_element(2,3) << endl;
    cout << "Test 3: dMatrix[3][3] = " << dMatrix.get_element(3,3) << endl;
    
    
    // set_element
    dMatrix.set_element(2, 3, 0.0);
    cout << "\nTest 4: the modified dMatrix = \n" << dMatrix;
    
    // product between a matrix and a scalar
    ElementType scal = 2.0;
    Matrix res1 = dMatrix*scal;
    cout << "\nTest 5: res1 = dMatrix * " << scal << " =\n" << res1;
   
    // transpose of a matrix
    Matrix res2 = res1.transpose();
    cout << "\nTest 6: res2 = res1 ^ T = \n" << res2;
    
    // the transpose of the transpose of any matrix should be the matrix itself
    cout << "\nTest 7: res1 ^ T ^ T = \n" << res1.transpose().transpose();
    
    // multiplying two incompatible matrices
    cout << "\nTest 8: res1 * res1 = " << res1* res1;
    
    // multiplying two compatible matrices
    Matrix res3 = res1 * res2;
    cout << "\nTest 9: res1 * res 2 = \n" << res3; 
    
   return 0;
} 

makefile (given by professor)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
OBJS = Matrix.o 
CC = g++
DEBUG = -g
CFLAGS = -Wall -c $(DEBUG)
LFLAGS = -Wall $(DEBUG)

all : test

test: $(OBJS) test.o
	$(CC) $(LFLAGS) $(OBJS) test.o -o test

Matrix.o : Matrix.h Matrix.cpp
	$(CC) $(CFLAGS) Matrix.cpp

test.o: test.cpp Matrix.h
	$(CC) $(CFLAGS) test.cpp

clean :
	rm *.o *~ test 


Error that I get when I run this program:
g++ -Wall -c -g Matrix.cpp
g++ -Wall -c -g test.cpp
test.cpp: In function âint main()â:
test.cpp:52: error: no match for âoperator<<â in âstd::operator<< [with _Traits = std::char_traits<char>](((std::basic_ostream<char, std::char_traits<char> >&)(& std::cout)), ((const char*)"\012Test 7: res1 ^ T ^ T = \012")) << Matrix::transpose()()â
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/ostream.tcc:67: note: candidates are: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_ostream<_CharT, _Traits>& (*)(std::basic_ostream<_CharT, _Traits>&)) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/ostream.tcc:78: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_ios<_CharT, _Traits>& (*)(std::basic_ios<_CharT, _Traits>&)) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/ostream.tcc:90: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::ios_base& (*)(std::ios_base&)) [with _CharT = char, _Traits = std::char_traits<char>]
.
.
.
Matrix.h:36: note: std::ostream& operator<<(std::ostream&, Matrix&)
make: *** [test.o] Error 1
Could not put entire error limit because of character limit

What is wrong with my code?

You are trying to use a reference to a temporary
Change the declaration to
ostream & operator<< (ostream & out, const Matrix & aMatrix);

(you should use the display() method)
Last edited on
I have tried that and I still get the same error message
here is the code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
void Matrix::display(ostream & out) const
{
	if (col_num == 0 || row_num == 0)
	{
		out<<"Invalid Matrx";
	}
	else
	{

	for (int i = 0; i < row_num; i++)
	{
		for (int j = 0; j < col_num; j++)
			out << setw(7) << mydata[i][j];
		out << endl;
	}
	}
}

ostream & operator<< (ostream & out, Matrix & aMatrix)
{
	aMatrix.display(out);
	return out;
}
Last edited on
You've still not changed operator<< to take a const object as ne555 advised above.
I missed the constant, everything works now thanks
Topic archived. No new replies allowed.