Using Template Array in another class

I keep getting heap errors crashing my code (mid run-time or at exit) when I use a Template Array to store user input (for (double) monthly rainfall amounts). When I use a simple array, I get no errors and the code performs correctly, but I'm required to use a template array. My problem has something to do with the pointer *list in arrayTemplate.h, but I cannot narrow down how or where it's screwing up. Can anyone help me find my issue?
-----------------------------
main.cpp
----------------------------
1
2
3
4
5
6
7
8
9
10
11
#include <iostream>
#include "rainfallTracker.h"

int main()
{
	rainfallTracker chocobunny2010("Chocobunny County", 2010);
	chocobunny2010.getData();
	chocobunny2010.output();
	cin.get();
	return 0;
}


--------------------------------
arrayTemplate.h
--------------------------------
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
#ifndef ARRAYTEMPLATE_H
#define ARRAYTEMPLATE_H

#include <iostream>
#include <string>

using namespace std;

template <class elemType>
class arrayTemplate
{
public:
	
	int listSize() const;
		//return number of assigned elements
	int maxListSize() const;
		//return maximum number of elements
	void insertEnd(const elemType& insertItem);
		//insert insertItem into array at end of current list
	void retrieveAt(int location, elemType& retItem) const;
		//assign retItem to be the array element at location
	void highestValue(int& location, elemType& value) const;
		//assign value to be the largest array element in the list
	void lowestValue(int& location, elemType& value) const;
		//assign value to the smallest array element in the list

	arrayTemplate(int size = 12);
		//constructor - Array Size

	~arrayTemplate();
		//destructor
private:
	elemType *list;	//a pointer of type elemType
	int length;	//the current length of the list
	int maxSize;	//the maximum size allowed for the list
};

//return number of assigned elements
template <class elemType>
int arrayTemplate<elemType>::listSize() const
{
	return length;
}

//return maximum number of elements
template <class elemType>
int arrayTemplate<elemType>::maxListSize() const
{
	return maxSize;
}

//insert insertItem into array at end of current list
template <class elemType>
void arrayTemplate<elemType>::insertEnd(const elemType& insertItem)
{
	if (length == maxSize)
		cout << "\tArray already full. Cannot insert element." << endl;
	else
	{
		list[length] = insertItem;
		length++;
	}
}

//assign retItem to be the array element at location
template <class elemType>
void arrayTemplate<elemType>::retrieveAt(int location, elemType& retItem) const
{
	if(location >= length)
		cout << "\tLocation past end of current array length. Cannot insert element" << endl;
	else if (location < 0)
		cout << "\tLocation less than 0. Cannot insert element" << endl;
	else
		retItem = list[location];
}

//assign value to be the largest array element in the list
template <class elemType>
void arrayTemplate<elemType>::highestValue(int& location, elemType& value) const
{
	elemType tmpValue = list[0];
	int tmpLocation = 0;
	for (int i = 1; i < length; i++)
		if (tmpValue < list[i])
		{
			tmpValue = list[i];
			tmpLocation = i;
		}
	value = tmpValue;
	location = tmpLocation;
}

//assign value to the smallest array element in the list
template <class elemType>
void arrayTemplate<elemType>::lowestValue(int& location, elemType& value) const
{
	elemType tmpValue = list[0];
	int tmpLocation = 0;
	for (int i = 1; i < length; i++)
		if (tmpValue > list[i])
		{
			tmpValue = list[i];
			tmpLocation = i;
		}
	value = tmpValue;
	location = tmpLocation;
}

//constructor - Array Size
template <class elemType>
arrayTemplate<elemType>::arrayTemplate(int size)
{
	if (size <= 0)
	{
		cout <<  "\tArray must have a size greater than 0. Creating an array of default size, 12." << endl;
		maxSize = 12;
	}
	else
		maxSize = size;
	length = 0;
	list = new elemType(maxSize);
}

template <class elemType>
arrayTemplate<elemType>::~arrayTemplate()
{
	delete [] list;
}

#endif /* !ARRAYTEMPLATE_H */ 
Last edited on
--------------------------------
rainTracker.h
--------------------------------
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
#ifndef RAINFALLTRACKER_H
#define RAINFALLTRACKER_H

#include <string>
#include "arrayTemplate.h"

class rainfallTracker
{
public :
	void getData();
		//verify and fill rainfall list with user input double values
	double verifyDblPrompt(int min, string prompt) const;
		//verify user input is a double value type greater than min
	void clearbuffer() const;
		//clear any excess text and failt states from cin buffer
	void output() const;
		//display the total rainfall, and the respective months and amount for the lowest and highest rainfalls
	double totalRainfall() const;
		//return the total rainfall for the whole year

	rainfallTracker(string location = "Unknown", int data = -1);
		//constructor

	~rainfallTracker();
		//destructor

private :
	arrayTemplate<double> rainfall; //array to hold rainfall totals for each month
	string monthsList[12];			//array to hold month names
	string countyName;				//name of the county for the rainfall data
	string year;					//year for the rainfall data
};

#endif /* !RAINFALLTRACKER_H */ 


------------------------------------
rainTracker.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
#include <iostream>
#include <string>
#include "arrayTemplate.h"
#include "rainfallTracker.h"

using namespace std;

//verify and fill rainfall list with user input double values
void rainfallTracker::getData()
{
	string prompt;

	for (int j = 0; j < 12; j++)
	{
		prompt = "Enter the rainfall (in inches) in " + countyName + " for " + monthsList[j] + " " + year + ": ";
		rainfall.insertEnd(verifyDblPrompt(0, prompt));
	}
}

//verify user input is a double value type greater than min
double rainfallTracker::verifyDblPrompt(int min, string prompt) const
{
	double tmpValue = min - 1; //variable for store unverified user input value, initialized out of bounds
	while (tmpValue < min)
	{
		cout << prompt;
		while (!(cin >> tmpValue))
		{
			cout << "\tInvalid. Input an double value.";
			clearbuffer();
			cout << endl << prompt;
		}
		if (tmpValue < min)
			cout << "\tInvalid. Input an double value of " << min << " or more." << endl;
		clearbuffer();
	}
	return tmpValue;
}

//clear any excess text and failt states from cin buffer
void rainfallTracker::clearbuffer() const
{
	cin.clear();
	cin.ignore(2000, '\n');
}

//display the total rainfall, and the respective months and amount for the lowest and highest rainfalls
void rainfallTracker::output() const
{
	double mostRain;
	double leastRain;
	int wettest;
	int driest;

	rainfall.lowestValue(driest, leastRain);
	rainfall.highestValue(wettest, mostRain);

	cout << endl << "\t" << year << " Rain Report for " << countyName << endl;
	cout << endl << "\tTotal rainfall: " << totalRainfall() << " inches";
	cout << endl << "\tThe least rain fell in ";
	cout << monthsList[driest];
	cout << " with " << leastRain << " inches.";
	cout << endl << "\tThe most rain fell in ";
	cout << monthsList[wettest];
	cout << " with " << mostRain << " inches.";
}

//return the total rainfall for the whole year
double rainfallTracker::totalRainfall() const
{
	double total = 0;
	double nextMonthRain;
	for (int j = 0; j < 12; j++)
	{
		rainfall.retrieveAt(j, nextMonthRain);
		total += nextMonthRain;
	}
	return total;
}

//constructor to initialize monthsList, rainfall, countyName and year
rainfallTracker::rainfallTracker(string name, int date)
{
	//arrayTemplate<double> rainfall(12);
	countyName = name;
	year = to_string(date);

	monthsList[0] = "January";
	monthsList[1] = "February";
	monthsList[2] = "March";
	monthsList[3] = "April";
	monthsList[4] = "May";
	monthsList[5] = "June";
	monthsList[6] = "July";
	monthsList[7] = "August";
	monthsList[8] = "September";
	monthsList[9] = "October";
	monthsList[10] = "November";
	monthsList[11] = "December";
}

//destructor
rainfallTracker::~rainfallTracker()
{
	rainfall.~arrayTemplate();
}


(SIDE NOTE:) Can anyone tell me how I can have a template array in rainfallTracker object without initializing it before the constructor for rainfallTracker? Including rainfall (of type arrayTemplate<double>) as a data member calls the constructor for arrayTemplate and automatically uses the default size since I can't specify size in the declaration for variable rainfall. Attempting to initialize rainfall to another size in the rainfallTracker constructor does nothing at all to affect the data member (I'm assuming it creates a rainfall variable of that size only for the scope of the constructor which is destroyed after the constructor ends). The default value won't hurt my program here since I have it defaulting to a size of 12, which is what I need, but that could be a problem in other circumstances.
Last edited on
Two problems. FIrst, don't call the arrayTemplate dtor in rainfallTracker's dtor. It will be called automatically. So rainfallTracker doesn't need a dtor at all.

Secondly, you are not creating the array properly in arrayTemplate. You need to use square brackets:

 
	list = new elemType[maxSize];

The way you are doing it (with regular parentheses) just makes a single element initialized to the value in parentheses.

As for initializing the size of the array in rainfallTracker's ctor, the syntax is like this:

1
2
rainfallTracker::rainfallTracker(string name, int date) : rainfall(12)
{

Last edited on
Topic archived. No new replies allowed.