So, I've tested vector and it seems to be running fine. However, I'm trying to implement a basic Stack class built off of my Vector class. I keep running into these errors when I go to build:
stack.h(4): error C2955: 'Vector' : use of class template requires template argument list
followed by:
vector.h(11) : see declaration of 'Vector'
stack.h(13) : see reference to class template instantiation 'Stack<T>' being compiled
Here is the Vector.h file:
#include<iostream>
using namespace std;
const int SIZEFACTOR = 4;
template <class T>
class Vector{
private:
unsigned int size_Of_Vector; // # of Items in list
unsigned int total_Vector_Capacity;//Total Capacity
T * vector_array;//Items themselves
public:
Vector();
~Vector();
void push_back(const T &e);
void pop_back();
bool empty();
int size() const;
void growVector();
void shrinkVector();
void shrinkToSize();
int currentCapacity() const;
//Operator
const T & operator [] (int index){
if((index >= size_Of_Vector) || index < 0){
cout << "ERROR! Index not used: " << index
<< " (max = " << size_Of_Vector << ")" << endl;
return EXIT_FAILURE;
}
return vector_array[index];
};//End Operator
};//End Header Definition
template <class T>
Vector<T>::Vector(){//Constructor
total_Vector_Capacity = 2;//Initially two items
size_Of_Vector = 0;//Nothing is in the vector yet
vector_array = new T [total_Vector_Capacity];//Initially two items
}
template <class T>
Vector<T>::~Vector (){//Destructor
total_Vector_Capacity = 0;
size_Of_Vector = 0;
delete [] vector_array;
}
template <class T>
void Vector<T>::growVector(){
total_Vector_Capacity = total_Vector_Capacity * SIZEFACTOR; //Quarter Size
//Temp Array
T * temp_array;
temp_array = new T [total_Vector_Capacity];
//Copy
for(unsigned int i = 0; i < size_Of_Vector; i++){
temp_array[i] = vector_array[i];
}
//Delete old array
delete [] vector_array;
//Re-initilize main array
vector_array = new T [total_Vector_Capacity];
//Copy old Data back to original array
for(unsigned int i = 0; i < size_Of_Vector; i++){
vector_array[i] = temp_array[i];
}
//Delete temp array
delete [] temp_array;
}
template <class T>
void Vector<T>::shrinkVector(){
total_Vector_Capacity = (int) (total_Vector_Capacity / SIZEFACTOR); //Quarter Size
//Temp Array
T * temp_array;
temp_array = new T [total_Vector_Capacity];
//Copy
for(unsigned int i = 0; i < size_Of_Vector; i++){
temp_array[i] = vector_array[i];
}
//Delete old array
delete [] vector_array;
//Re-initilize main array
vector_array = new T [total_Vector_Capacity];
//Copy old Data back to original array
for(unsigned int i = 0; i < size_Of_Vector; i++){
vector_array[i] = temp_array[i];
}
//Delete temp array
delete [] temp_array;
}
template <class T>
void Vector<T>::shrinkToSize(){
total_Vector_Capacity = size_Of_Vector; //Quarter Size
//Temp Array
T * temp_array;
temp_array = new T [total_Vector_Capacity];
//Copy
for(unsigned int i = 0; i < size_Of_Vector; i++){
temp_array[i] = vector_array[i];
}
//Delete old array
delete [] vector_array;
//Re-initilize main array
vector_array = new T [total_Vector_Capacity];
//Copy old Data back to original array
for(unsigned int i = 0; i < size_Of_Vector; i++){
vector_array[i] = temp_array[i];
}
//Delete temp array
delete [] temp_array;
}
template <class T>
void Vector<T>::push_back(const T &e){
if(size_Of_Vector == total_Vector_Capacity){//Resize if size equals capacity
cout << "\nGrow now\n";
growVector();
}
vector_array[size_Of_Vector]=e;
size_Of_Vector++;//Increase Vector Size
}
template <class T>
void Vector<T>::pop_back(){
if(size_Of_Vector == (int)(total_Vector_Capacity/SIZEFACTOR)){//Resize if size equals capacity
cout << "\nShrink now\n";
shrinkVector();
}
size_Of_Vector--;//Increase Vector Size
}
template <class T>
bool Vector<T>::empty(){
if(size_Of_Vector==0){
return true;
}
else{
return false;
}
}
template <class T>
int Vector<T>::size() const{
return size_Of_Vector;
}
template <class T>
int Vector<T>::currentCapacity() const{
return total_Vector_Capacity;
}
and stack.h:
template <class T>
class Stack : public Vector{
private:
Vector<T> stack;
public:
Stack(){};
void push(T x) {stack.push_back(&x)};
void pop(){stack.pop_back()};
bool empty(){stack.empty()};
};
You have defined Vector<T> as a member of Stack already, it's not necessary to inherit from Vector
Update
template <class T>
class Stack : public Vector{
//...
};
To:
template <class T>
class Stack {
Vector<T> stack;
//...
};
Or if you want to inherit from a template class, you need to provide template parameter
template <class T>
class Stack : public Vector<T>{
// ^^^
Note:
You miss a few semicolons in Stack function definition and a bug in Stack::push_back as well, I may suggest update to below:
template <class T>
class Stack
{
private:
Vector<T> stack;
public:
Stack(){};
void push(T const& x) {stack.push_back(x);}
void pop(){stack.pop_back();}
bool empty(){return stack.empty();}
};
Related
Sorry if this has been answered before. I searched for resizing dynamic arrays and all the advice seems to be use STL Vector, but I'm doing an assignment where the point is to make my own, minimal, vector template class.
My vector class needs to store a dynamic array of structs created from reading from an input file. One of the things it has to do is resize when full. It works up to a point - processes 5121 lines out of 52207 lines and then crashes with error "Process returned -1073741819 (0XC0000005)".
I've looked around and found that this is a memory allocation error. I'm very new to programming and C++, and I'm stumped as to what in my program is causing this. I assume it is in my resizing the array code. Any help would be greatly appreciated!
My vector template code:
#ifndef VECTOR_H
#define VECTOR_H
#include <iostream>
using namespace std;
template <class T>
class Vector {
public:
/// Constructor
Vector();
/// Copy constructor
Vector(const Vector<T>& otherVector);
/// Destructor
virtual ~Vector();
/// assignment operator
const Vector<T>& operator= (const Vector<T>&);
/// methods
void addElement(const T& newElement);
T getElement(int index) const;
int getLength() const;
protected:
int arraySize;
int length;
T *p;
};
template <class T>
Vector<T>::Vector()
{
arraySize = 10;
length = 0;
p = new T[arraySize];
}
template <class T>
Vector<T>::Vector(const Vector& otherObject)
{
arraySize = otherObject.arraySize;
length = otherObject.length;
p = new T[arraySize];
for(int i = 0; i < length; i++)
p[i] = otherObject.p[i];
}
template <class T>
Vector<T>::~Vector()
{
delete [] p;
}
template <class T>
const Vector<T>& Vector<T>::operator= (const Vector<T>& newVector)
{
if(this != &newVector)
{
delete [] p;
arraySize = newVector.arraySize;
length = newVector.length;
p = new T[arraySize];
for(int i = 0; i < length; i++)
p[i] = newVector.p[i];
}
return *this;
}
template <class T>
void Vector<T>::addElement(const T& newElement)
{
if(length == arraySize)
{
// create a new resized array
T *temp;
temp = new T[arraySize*2];
// copy elements of p into temp
for(int i = 0; i < length; i++)
{
temp[i] = p[i];
}
// delete p and create new p and set equal to temp
delete [] p;
arraySize *= 2; // set array size to double
p = new T[arraySize];
p = temp;
// delete temp array
delete [] temp;
// add new element and incerement length;
p[length] = newElement;
length++;
}
else
{
p[length] = newElement;
length++;
}
}
template <class T>
T Vector<T>::getElement(int index) const
{
return p[index];
}
template <class T>
int Vector<T>::getLength() const
{
return length;
}
#endif
You have an error in your resize logic. Its all well and good until you get here.
p = new T[arraySize];
p = temp;
delete [] temp;
You allocate a new array and then immediately have p point to the data pointed to by temp. And then you delete the data pointed by temp which is the same as p which means p points to freed memory; it is a dangling reference and it is undefined to access anything through p
However, it is simple to fix: remove the allocation and deletion, you only need the line with the assignment:
// p = new T[arraySize];
p = temp;
// delete [] temp;
You don't need new space for p, temp already got it. Just give it to p. And then you don't delete temp, because p is managing it.
I had to build a dynamic array class from scratch myself, and I also tried to extend it with a (set like) function to add new elements into the array, it compiles well, but the program crashes, since it has some memory leakages.
Please try and help me, I'm on a short notice at school.
The array class
template <class T>
class Array
{
int n; /// size
T* data;
public:
explicit Array(int n): n(n) { adat=new T[n]; }
Array(const Array&);
Array& operator=(const Array&);
~Array();
T& operator[](int idx) { return data[idx]; }
int size() { return n; }
int lookfor(T);
void add(T);
void del();
};
DEFINITIONS
template <class T>
Array<T>::Array(const Array<T>& t)
{
n=t.n;
data=new T[n];
for (int idx=0; idx<n; ++idx)
data[idx]=t.data[idx];
}
/**
Operator=
*/
template <class T>
Array<T>& Array<T>::operator=(const Array<T>& t)
{
if (this==&t) return *this;
delete[] data;
n=t.n;
data=new T[n];
for (int idx = 0; idx < n; ++idx)
data[idx]=t.data[idx];
return *this;
}
/**
dtor
*/
template <class T>
Array<T>::~Array()
{
del();
}
This must be the wrong part
template <class T>
int Array<T>::lookfor(T el)
{
for(int idx = 0; idx < n; ++idx)
if(data[idx] == el)
return idx;
return -1;
}
/**
add
*/
template <class T>
void Array<T>::add(T el)
{
if(lookfor(elem) != -1)
{
T* temp = new T[n + 1];
for (int idx = 0; idx < n; ++idx)
temp[idx]=data[idx];
temp[n + 1] = el;
del();
data = temp;
++n;
}
}
template <class T>
void Array<T>::del()
{
for(int idx = 0; idx < n; ++idx)
delete data[idx];
delete[] data;
}
The code it fails with:
Control ctrl;
ctrl.add(new Room());
ctrl.add(new Room());
Control and Room are both subclasses of the array. Like Control : publicArray < Room* >
Get rid of the loop in del() that deletes all the data[idx] elements. data is not an array of pointers, it's an array of values of type T, so you can't delete them. Even if you make an array of pointers, these pointers came from the caller to add, and they're owned by that part of the program, not the Array class. You also don't want to delete all the old pointers when you add an element to the array, because the new data array still contains those pointers.
Calling delete on something that wasn't created using new results in undefined behavior, which is likely causing your crash.
I am trying to read some values remember them in object dep, and then show them. It shows random values and crashes. Can you tell me what is wrong in my program, it shoul be something about allocation..
#include<iostream>
)
{
std::cout<
and those are Wagon.h and Stack.h
template <typename T>
class Stack
{
T *stackArray;
....
Stack();
~Stack();
void push( T x );
void show();
void add(int M);
};
template <typename T>
Stack<T>::Stack()
{
stackArray = NULL;
topLevel = 0;
}
template <typename T>
Stack<T>::~Stack()
{
if ( stackArray != NULL )
delete [] stackArray;
}
void Wagon::printId()
{
std::cout<<id<<" ";
}
and main:
dep.addVagL(0,9);
dep.showDepot(2,2);
You can begin fixing your code by allocating the lines array in the Depot constructor:
Depot::Depot(int N, int M)
{
lines = new Stack<Wagon>[N];
for (int i=0; i<N; i++)
{
lines[i].add(M);
}
}
I created a new project in Xcode 5.0 to implement a Queue class as following:
I created a .h file called QueueArray.h and it contains the following:
#ifndef __Queue__QueueArray__
#define __Queue__QueueArray__
#include <iostream>
template <class T>
class QueueArray
{
public:
QueueArray(int cap);
~QueueArray();
void Enqueue(T& val);
T Dequeue(void);
T GetFirst(void);
T GetLast(void);
bool IsEmpty(void);
bool IsFull(void);
void Clear(void);
private:
T* data;
int capacity, size, first, last;
};
#endif
and a .cpp file called QueueArray.cpp that contains the following:
#include "QueueArray.h"
using namespace std;
template <class T>
QueueArray<T>::QueueArray(int cap)
{
capacity = cap;
data = new T[capacity];
size = 0;
first = last = -1;
}
template <class T>
QueueArray<T>::~QueueArray(void)
{
delete [] data;
}
template <class T>
void QueueArray<T>::Enqueue(T& el)
{
if(IsFull() == true)
{
printf("\n Can't enqueue into a full queue!");
return;
}
if(IsEmpty() == true)
first = last = 0;
else if(last == capacity-1)//if at the last entry
last = 0; //wrap around to the first entry
else
last++;
data[last] = el;
size++;
}
template <class T>
T QueueArray<T>::Dequeue()
{
if(IsEmpty() == true)
{
printf("\n Can't dequeue from an empty queue!");
return -1;
}
T el = data[first];
if(first == last) //if only one element in queue
last = first = -1; //we'll get an empty queue
else if(first == capacity-1) //if at the last entry
first = 0; //wrap around to the first entry
else //normal case
first++;
size--;
return el;
}
template <class T>
T QueueArray<T>::GetFirst()
{
return data[first];
}
template <class T>
T QueueArray<T>::GetLast()
{
return data[last];
}
template <class T>
bool QueueArray<T>::IsEmpty(void)
{
return size == 0;
}
template <class T>
bool QueueArray<T>::IsFull(void)
{
return size == capacity;
}
and a main.cpp file that contains the following:
#include <iostream>
#include "QueueArray.h"
using namespace std;
int main(int argc, const char * argv[])
{
QueueArray<int> q(100);
for (int i=0; i<100; i++)
{
q.Enqueue(i);
}
for (int i=0; i<100; i++) {
cout<<q.Dequeue()<<endl;
}
return 0;
}
When I try to run the project, a message appears saying "Build Failed" and here is a screenshot of the errors:
How to fix that?
The compiler needs to see the definition of the Template before using it.
http://www.parashift.com/c++-faq-lite/templates-defn-vs-decl.html
There are more than one solution:
a. Move the definitions from .cpp file to the .h file
b. Use the export keyword if your compiler supports
http://www.parashift.com/c++-faq-lite/separate-template-fn-defn-from-decl-export-keyword.html
c. Add an inline declaration:
http://www.parashift.com/c++-faq-lite/separate-template-fn-defn-from-decl.html
You need to include the template definitions in-line with their declarations. An easy solution to this is to rename QueueArray.cpp to something like QueueArray_impl.h and #include it from the bottom of QueueArray.h
#ifndef __Queue__QueueArray__
#define __Queue__QueueArray__
#include <iostream>
template <class T>
class QueueArray
{
public:
QueueArray(int cap);
~QueueArray();
void Enqueue(T& val);
T Dequeue(void);
T GetFirst(void);
T GetLast(void);
bool IsEmpty(void);
bool IsFull(void);
void Clear(void);
private:
T* data;
int capacity, size, first, last;
};
#include "QueueArray_impl.h"
#endif
I don't know why my code is seg faulting, im assuming im looking at a point in the queue where theres nothing there, but I thought that I do push elements onto the queue.
heres my code:
template <typename T>
class btree {
public:
btree(size_t maxNodeElems);
~btree() {}
struct node {
list <T> elements;
node *lvl;
};
private:
size_t maxNodeElems;
node* root;
};
template <typename T>
btree<T>::btree(size_t maxNodeElems) {
if (maxNodeElems > 0) max = maxNodeElems;
root = new node;
root->lvl = new node*[max+1];
for (int i = 0; i < (int) max+1; i++) root->lvl[i] = new node;
}
template <typename T>
std::ostream& operator<<(std::ostream& os, const btree<T>& tree) {
queue <typename btree<T>::node*> q;
q.push(tree.root);
int loop = 0;
while (!q.empty()) {
loop++;
typename btree<T>::node* temp = q.front();
int i = 0;
class list <T>::iterator itr = temp->elements.begin();
for (; itr != temp->elements.end(); ++itr) {
os << *itr << " ";
if (!temp->lvl[i]->elements.empty()) {
q.push(temp->lvl[i]);
}
i++;
}
q.pop();
}
return os;
}
could someone help me out, im lost because when I check if the if statement is working inside the for loop, it does go into it, but im not sure if its pushing
EDIT: more code
template <typename T>
pair <typename btree<T>::iterator, bool> btree <T>::insert (const T& elem) {
pair <typename btree<T>::node, bool> start;
start = addElement (elem, root);
pair <typename btree<T>::iterator, bool> final;
return final;
}
template <typename T>
pair <typename btree<T>::node, bool> btree<T>::addElement (const T& e, typename btree<T>::node*& n) {
pair <typename btree<T>::node, bool> elemPair;
if (n->elements.size() == max) {
int count = 0;
class list <T>::iterator itr = n->elements.begin();
for (; itr != n->elements.end(); ++itr) {
count++;
if (e < *itr) {
count--;
elemPair = addElement (e, n->lvl[count]);
} else if (e == *itr) return make_pair (*n, false);
}
} else {
n->elements.push_back(e);
n->elements.sort();
}
return make_pair(*n, true);
}
in my test.cpp:
int main (void) {
btree<char> b(2);
b.insert('Z'); b.insert('J'); b.insert('Y');
cout << b;
return 0;
}
The code you post doesn't compile and so I can't verify your error.
The following does compile and so might provide some help. Its similar to the code you provided.
However, the following is not good code - for example, you need to be vary careful about using the new keyword in a constructor, because exception handing in a constructor is more difficult (and there is the chance of an allocation exception being thrown).
template <typename T>
class btree {
public:
btree(size_t maxNodeElems);
//if your using new then you need to delete - do that in the destructor.
~btree();
struct node {
list <T> elements;
//you use this as a pointer to an array,
// it can be demoted to a double pointer -
// but not a single pointer as you had.
node ** lvl;
};
private:
size_t maxNodeElems; //you don't actually use this variable in your code
node* root;
//You are doing memory allocations in the constructor,
// therefore need to overload operator= and copy constructor.
// Since we are not overloading these, we make them private.
void operator=(const btree&);
btree(const btree&);
};
//In your code you had a undeclared variable max.
// No idea what it was or why you had it - removed.
template <typename T>
btree<T>::btree(size_t v_maxNodeElems)
: maxNodeElems(v_maxNodeElems) // construct the variable you define
{
root = new node;
root->lvl = new node*[maxNodeElems+1]; //root->lvl is a double pointer
for (int i = 0; i < (int) maxNodeElems+1; i++)
root->lvl[i] = new node;
}
//delete in reverse order to you constructing
template <typename T>
btree<T>::~btree() {
for (int i = 0; i < (int) maxNodeElems+1; i++)
delete root->lvl[i]; //first the elements of the array
delete[] root->lvl; //then the array - note the delete[]
delete root; //then the root.
}
int
main (int ac, char **av)
{
btree<char> b(2);
}