Table Class <template> question

Here is a Table Class

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
template <class elementType>
class Table {
public:
   Table( int = 10, int = 10 );  // default constructor                       
   Table( const Table< elementType > & ); // copy constructor
   ~Table();                               
   
   void print() const;
   void inputValues();
   const Table< elementType > &operator=( 
      const Table< elementType > & );                                                          
   bool operator==( const Table< elementType > & ) const; 

   // Determine if two arrays are not equal and
   // return true, otherwise return false (uses operator==).
   bool operator!=( const Table< elementType > &right ) const  
      { return !( *this == right ); }  

   elementType &operator()( int, int );              
   const elementType &operator()( int, int ) const;  
private:
   int rows;             // number of rows in array
   int columns;          // number of columns in array

   /* write declaration for private data member ptr, a pointer 
      that contains the dynamically allocated array */
	elementType *ptr; 
};


Assuming that I have correctly done this:

1
2
3
4
5
 /* write declaration for private data member ptr, a pointer 
      that contains the dynamically allocated array */
	
elementType *ptr; 


How can I:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

template < class elementType >
Table< elementType >::Table( int r, int c )
{
   int rows = ( r > 0 ? r : 10 );
   int columns = ( c > 0 ? c : 10 );
   /* write code to allocate dynamically an array with rows * 
      columns elements of type elementType */
   int size = rows*columns;
   
   assert( ptr != 0 );    

   for ( int i = 0; i < rows * columns; i++ )
      ptr[ i ] = 0; // initialize array       
}


I tried

 
ptr (new elementType[size]); 


Which doesn't seem to work because Table expects multiple parameters.

Can someone point me in the right direction? What am I missing here..
Last edited on
ptr = new elementType[size];

then to clean up:

delete[] ptr;
That code seems to create the pointer..

I have a

1
2
3

delete[]ptr; 


destructor declared. When I compile the code I get linker error 2019...

1
2
Table.obj : error LNK2019: unresolved external symbol "public: char & __thiscall Table<char>::operator()(int,int)" (??R?$Table@D@@QAEAADHH@Z) referenced in function _main
Table.obj : error LNK2019: unresolved external symbol "public: int & __thiscall Table<int>::operator()(int,int)" (??R?$Table@H@@QAEAAHHH@Z) referenced in function _main


Thoughts?

RC325
Template functions and classes must be completely implemented within the header file in which they are declared.
I finished declaring my functions however - get some bizarre output. Actually the debugger stops it and I get a screen full of 0's and other strange floating point numbers.

I would guess that I did something wrong in the implementation of my overloads here

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

/* write definition for overloaded operator== */
template <class elementType>
bool Table<elementType>::operator ==(const Table <elementType> &right) const {
   if ( &right == this ) 
		return true;
	else
		return false;
}


/* write definition for overloaded subscript operator for
    non-const Tables; reference return creates an lvalue */


template < class elementType >
elementType &Table< elementType >
   ::operator()( int s1, int s2 )
{
   assert( 0 <= s1 && s1 < rows );
   assert( 0 <= s2 && s2 < columns );

   return ptr[ rows * s1 + s2  ]; 
}



(for anyone curious in seeing the whole thing)

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

//CSC234 Advanced C++
// table.h
// 

#ifndef TABLE_H
#define TABLE_H

#include <iostream>

using std::ostream;
using std::istream;

/* write code that specifies Table as a template definition 
   with type parameter elementType */
template <class elementType>
class Table {
public:
   Table( int = 10, int = 10 );  // default constructor                       
   Table( const Table< elementType > & ); // copy constructor
   ~Table();                               
   
   void print() const;
   void inputValues();
   const Table< elementType > &operator=( 
      const Table< elementType > & );                                                          
   bool operator==( const Table< elementType > & ) const; 

   // Determine if two arrays are not equal and
   // return true, otherwise return false (uses operator==).
   bool operator!=( const Table< elementType > &right ) const  
      { return !( *this == right ); }  

   elementType &operator()( int, int );              
   const elementType &operator()( int, int ) const;  
private:
   int rows;             // number of rows in array
   int columns;          // number of columns in array

   /* write declaration for private data member ptr, a pointer 
      that contains the dynamically allocated array */
	elementType *ptr; 
};

template < class elementType >
Table< elementType >::Table( int r, int c )
{
   int rows = ( r > 0 ? r : 10 );
   int columns = ( c > 0 ? c : 10 );
   /* write code to allocate dynamically an array with rows * 
      columns elements of type elementType */
   int size = rows*columns;
   ptr = new elementType[size];
	
   assert( ptr != 0 );    

   for ( int i = 0; i < rows * columns; i++ )
      ptr[ i ] = 0; // initialize array       
}

template < class elementType >
Table< elementType >::Table(
   const Table< elementType > &init ) 
{
   rows = init.rows;
   columns = init.columns;

   ptr = new elementType[ rows * columns ];
   assert( ptr != 0 );    

   for ( int i = 0; i < rows * columns; i++ )
      ptr[ i ] = init.ptr[ i ];  
}

template < class elementType >
Table< elementType >::~Table()
{
   delete [] ptr;         
}

template < class elementType >
const Table< elementType > &Table< elementType >
   ::operator=( const Table< elementType > &right )
{
   if ( &right != this ) {  
      
      if ( rows * columns != right.rows * right.columns ) {
         delete [] ptr;         
         rows = right.rows;     
         columns = right.columns;     
         ptr = new elementType[ rows * columns ]; 
         assert( ptr != 0 ); 
      }

      for ( int i = 0; i < rows * columns; i++ )
         ptr[ i ] = right.ptr[ i ];  
   }

   return *this;   
}

/* write definition for overloaded operator== */
template <class elementType>
bool Table<elementType>::operator ==(const Table <elementType> &right) const {
   if ( &right == this ) 
		return true;
	else
		return false;
}


/* write definition for overloaded subscript operator for
    non-const Tables; reference return creates an lvalue */


template < class elementType >
elementType &Table< elementType >
   ::operator()( int s1, int s2 )
{
   assert( 0 <= s1 && s1 < rows );
   assert( 0 <= s2 && s2 < columns );

   return ptr[ rows * s1 + s2  ]; 
}


 
template < class elementType >
const elementType &Table< elementType >
   ::operator()( int s1, int s2 ) const
{
   assert( 0 <= s1 && s1 < rows );
   assert( 0 <= s2 && s2 < columns );

   return ptr[ columns * s1 + s2  ]; // rvalue
}

template < class elementType >
void Table< elementType >
   ::inputValues()
{
   for ( int i = 0; i < rows * columns; i++ )
      cin >> ptr[ i ];
}

template < class elementType >
void Table <elementType> :: print() const
{
  int i = 0;
   for (i = 0; i < rows * columns; i++ ) {
      cout << setw( 6 ) << ptr[ i ];

      if ( ( i + 1 ) % columns == 0 )
         cout << endl;
   }

   if ( i % columns != 0 )
      cout << endl;
}
#endif



Thanks

RC325

There are a number of major problems.

Lines 48 and 49 shadow the member variables of the same names.

asserting the return value of new against non-NULL is pointless since the throwing
version of new never returns NULL (it throws std::bad_alloc instead, which you don't
catch).

operator== is totally wrong; it is comparing the address of the righthand side against the
address of the lefthand side, not the contents of each.

We won't even go into exception safety, as I'm sure you aren't worried about it.
I'll ignore your comments about 48 and 49 and (while I'm sure you are correct) and concentrate on fixing the == function.

I'm sure that is probably the cause of the weird output.

RC325
I redefined my ==

as

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

template <class elementType>
bool Table<elementType>::operator ==(const Table <elementType> &right) const {	 
	int total = 0;
	 
	for (int i = 0; i < rows*coumns; i++)
	   {
		   if (rows = right.rows && columns = right.columns)
		 {
			 return true; 
			total++
			 }
		 else
			 total--

		 if (total == rows*columns)
			 return true;
		 else 
			return false;
}


And now I get an 1120 linker error?

I really wish I knew what I was doing (feeling totally lost here).

RC325
It is still not right.

What linker error are you getting?

You need to fix 48 and 49 or nothing will work even if it compiles.
It's error LNK1120.

*sigh* I don't understand what they are trying to do with lines 48+49 so I'm not sure how to fix it.

RC325
It's error LNK1120.


Most of us don't have error codes memorized. Please post the full error.
Lines 48 and 49 are declaring local variables named row and col and assigning values to them, but I'm
sure the intention is to assign the class members row and col those values instead.

The operator==() implementation needs a second look, as well. It is mistakenly using the assignment operator (=) in the conditions on line 8.

Also, counting how many are equivalent and comparing that count to the total number of items compared is kind of silly. All you have to do is loop through them and compare until either 1) an element is not equivalent or 2) all of them were equivalent.

EDIT: My mistake, it's not even comparing the data it is only comparing the size--which does not require a loop at all.
Last edited on
Topic archived. No new replies allowed.