Using templates in classes also operator overloading

I am trying to add two objects via operator overloading and some sort of runtime error occurs. just cant figure it out.



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
#include<iostream>
using namespace std;
//forward declararions
template <class T>
class Matrix2d;
template <class T>
ostream& operator<<(ostream& out, const Matrix2d<T>& obj);
template <class T>
istream& operator>>(istream& in,const Matrix2d<T>& obj);

template <class T>
class Matrix2d
{
    private:
        int rows;
        int columns;
        T **data;
    public:
        Matrix2d<T>();
        Matrix2d<T>(int,int);
        ~Matrix2d<T>();
        friend ostream&  operator<< <T> (ostream &, const Matrix2d<T> &);
        friend istream& operator>> <T>(istream & ,const Matrix2d<T>&);
        Matrix2d<T> operator+(const Matrix2d&);
};
template <class T>
Matrix2d<T>::~Matrix2d()
{
    for(int i =0 ; i < rows;i++)
        delete data[i];
    delete data;
}
template <class T>
Matrix2d<T>::Matrix2d() //parameterless constructor
{
    rows =1;
    columns=1;
    data = new T*[rows];
    for(int i =0 ; i < rows;i++)
    {
        data[i] = new T[columns];
    }
    for(int i =0 ; i< rows ; i++)
    {
        for(int j =0 ;j<columns ; j++)
        {
            data[i][j]=0;
        }
    }
}
template <class T>
Matrix2d<T>::Matrix2d(int r, int col) //constructor with parameters
{
    rows =r;
    columns=col;
    data = new T*[rows];
    for(int i =0 ; i < rows;i++)
    {
        data[i] = new T[columns];
    }
    for(int i =0 ; i< rows ; i++)
    {
        for(int j =0 ;j<columns ; j++)
        {
            data[i][j]=0;
        }
    }
}
//extraction operator
template <class T>
ostream& operator<<(ostream& out, const Matrix2d<T>& obj)
{
    for(int i =0 ; i< obj.rows ; i++)
    {
        for(int j =0 ;j<obj.columns ; j++)
        {
            out << obj.data[i][j];
        }
        cout << endl;
    }
    return out;
}
//insertion operator
template <class T>
istream& operator >> (istream& in, const Matrix2d<T>& obj)
{
    for(int i =0 ; i< 2 ; i++)
    {
        for(int j =0 ;j<1 ; j++)
        {
            cout << "Enter data in ( "<<i<<","<<j<<" ) : ";
            in>> obj.data[i][j];
        }
        cout << endl;
    }
    return in;
}
//addition operator (where the problem is)
//addition operator (where the problem is)
//addition operator (where the problem is)
template <class T>
Matrix2d<T> Matrix2d<T>::operator +(const Matrix2d<T>& obj)
{
    Matrix2d<int> temp(rows,columns);
    for(int i =0 ; i< rows ; i++)
    {
        for(int j =0 ;j<columns ; j++)
        {
            temp.data[i][j]=data[i][j]+obj.data[i][j];
        }
    }
   return temp;
}

int main()
{
    Matrix2d<int> o(2,2);
    Matrix2d<int> o2(2,2);
    Matrix2d<int> o3(2,2);
    o3 = o+o2;
    return 0;
}
I see. The problem is in your operator = (or the absence of it). Now two objects point to the same data - the temporary value returned by operator + and o3. Due to this, their destructors will try to destroy the same memory twice, which is a problem. You have to write operator = (and copy constructor) that would make a deep copy of your matrix.
thanks for the advice hamsterman it helped alot.... but i am stuck at a new place...
its not adding properly...the result is again just object o2 where as it should be addition of o2 and o
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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#include<iostream>
using namespace std;
//forward declararions
template <class T>
class Matrix2d;
template <class T>
ostream& operator<<(ostream& out, const Matrix2d<T>& obj);
template <class T>
istream& operator>>(istream& in,const Matrix2d<T>& obj);

template <class T>
class Matrix2d
{
    private:
        int rows;
        int columns;
        T **data;
    public:
        Matrix2d<T>();
        Matrix2d<T>(int,int);
        ~Matrix2d<T>();
        Matrix2d<T>(const Matrix2d<T>&);
        friend ostream&  operator<< <T> (ostream &, const Matrix2d<T> &);
        friend istream& operator>> <T>(istream & ,const Matrix2d<T>&);
        Matrix2d<T> operator+(const Matrix2d<T>&);
        Matrix2d<T> operator=(const Matrix2d&);
};
template <class T>
Matrix2d<T>::~Matrix2d()
{
    for(int i =0 ; i < rows;i++)
        delete data[i];
    delete data;
}
template <class T>
Matrix2d<T>::Matrix2d() //parameterless constructor
{
    rows =1;
    columns=1;
    data = new T*[rows];
    for(int i =0 ; i < rows;i++)
    {
        data[i] = new T[columns];
    }
    for(int i =0 ; i< rows ; i++)
    {
        for(int j =0 ;j<columns ; j++)
        {
            data[i][j]=0;
        }
    }
}
template <class T>
Matrix2d<T>::Matrix2d(int r, int col) //constructor with parameters
{
    rows =r;
    columns=col;
    data = new T*[rows];
    for(int i =0 ; i < rows;i++)
    {
        data[i] = new T[columns];
    }
    for(int i =0 ; i< rows ; i++)
    {
        for(int j =0 ;j<columns ; j++)
        {
            data[i][j]=0;
        }
    }
}
//copy constructor
template<class T>
Matrix2d<T>::Matrix2d(const Matrix2d<T>& obj)
{
    rows = obj.rows;
    columns = obj.columns;
    data = new T*[rows];
    for(int i =0 ; i < rows;i++)
    {
        data[i] = new T[columns];
    }
    for(int i =0 ; i < rows; i++)
    {
        for(int j =0 ; j<columns;j++)
        {
            data[i][j]= obj.data[i][j];
        }
    }
}
//extraction operator
template <class T>
ostream& operator<<(ostream& out, const Matrix2d<T>& obj)
{
    for(int i =0 ; i< obj.rows ; i++)
    {
        for(int j =0 ;j<obj.columns ; j++)
        {
            out << obj.data[i][j]<<" ";
        }
        cout << endl;
    }
    return out;
}
//insertion operator
template <class T>
istream& operator >> (istream& in, const Matrix2d<T>& obj)
{
    for(int i =0 ; i< obj.rows ; i++)
    {
        for(int j =0 ;j<obj.columns ; j++)
        {
            cout << "Enter data in ( "<<i<<","<<j<<" ) : ";
            in>> obj.data[i][j];
        }
        cout << endl;
    }
    return in;
}
//addition operator (where the problem is)
//addition operator (where the problem is)
//addition operator (where the problem is)
template <class T>
Matrix2d<T> Matrix2d<T>::operator +(const Matrix2d<T>& obj)
{
    Matrix2d<T> temp(rows,columns);
    for(int i =0 ; i< rows ; i++)
    {
        for(int j =0 ;j<columns ; j++)
        {
            temp.data[i][j]=data[i][j]+obj.data[i][j];
        }
    }
   return temp;
}
//Assignment operator
template <class T>
Matrix2d<T> Matrix2d<T>::operator=(const Matrix2d<T>& obj)
{
    Matrix2d<T> temp(rows,columns);
    for(int i =0 ; i< rows ; i++)
    {
        for(int j =0 ;j<columns ; j++)
        {
            temp.data[i][j]=obj.data[i][j];
        }
    }
    return temp;
}
int main()
{
    Matrix2d<int> o(2,2);
    Matrix2d<int> o2(2,2);
    cin >>o;
    cin >>o2;
    Matrix2d<int> o3(o);
    cout << o;
    cout <<o2;
    cout <<o3;
    o3 = o+o2;
    cout << o3;
    return 0;
}
just a quick question as how the dynamic array was destroyed in the destructor .... is this the correct way ..
Last edited on
Your operator = is wrong. It should instead be
1
2
3
4
5
6
7
8
9
10
11
12
template <class T>
Matrix2d<T>& Matrix2d<T>::operator=(const Matrix2d<T>& obj)
{
    for(int i =0 ; i< rows ; i++)
    {
        for(int j =0 ;j<columns ; j++)
        {
            data[i][j]=obj.data[i][j];
        }
    }
    return *this;
}


By the way, having the matrix as T** is a bit ugly. You could instead have T* and mimic [x][y] syntax with [y*rows+x]. Though I can't say that there is any benefit to that..
A better idea may be to drop dynamic memory altogether and add WIDTH and HEIGHT template parameters to your matrix. That would make sense and save you from some work.

@bluecoder
It seems fine to me. What would you want it to be?
Last edited on
@blue coder

Thanks for pointing out..... here is the correct way
1
2
3
4
5
6
7
template <class T>
Matrix2d<T>::~Matrix2d()
{
    for(int i =0 ; i < rows;i++)
        delete []data[i];
    delete []data;
}


@hamsterman

once again you have made my day :)
Topic archived. No new replies allowed.