Last function not displaying correct output - c++

I am not getting the expected output for the program that I have coded, I know that the implementation for the last function is incorrect. I don't know how to implement this so that it returns the last entry into the array, and doesn't remove it. The second question that I have is on the pop_back function, its supposed to remove last entry pushed into the vector and reduce it by one, and if it's empty do nothing. The way it is now it just reduces the vector by one. Thanks for your help in advance.
Driver
#include <iostream>
#include "vectorHeader.h"
using namespace std;
int main()
{
const char START = 'A';
const int MAX = 12;
// create a vector of doubles
myVector<char> vectD;
// push some values into the vector
for (int i = 0; i < MAX; i++)
{
vectD.push_back(START + i);
}
// remove the last element
vectD.pop_back();
// add another value
vectD.push_back('Z');
// test memory management
myVector<char> vectD2 = vectD;
// display the contents
cout << "\n[";
for (int i = 0; i < vectD2.size() - 1; i++)
{
cout << vectD2[i] << ", ";
}
cout << "..., " << vectD2.last() << "]\n";
system("PAUSE");
return 0;
}
Header
#include <iostream>
#include <iomanip>
#include <string>
#include <vector>
#include <fstream>
#include <stdexcept>
#include <array>
//Declaring constant
const int VECTOR_CAP = 2;
template <class T>
class myVector
{
private:
//Setting data members
T* vectorData;
int cap;
int numElements;
public:
//Default constructor
//Purpose: Creates a vector
//Parameters: None
//Returns: None
myVector();
//Parameterized constructor
//Purpose: Creates a vector capacity of n
//Parameters: None
//Returns: None
myVector(const T&);
//Copy Constructor
//Purpose: Copy data into vector
//Parameters: myVector object
//Returns: None
myVector(const myVector& copy)
{
numElements = copy.numElements;
vectorData = new T [numElements];
for (int i = 0; i < numElements; i++)
{
this->vectorData[i] = copy.vectorData[i];
}
}
//Destructor
//Purpose:Deletes any dynamically allocated storage
//Parameters: None
//Returns: None
~myVector();
//Size function
//Purpose: returns the size of your vector
//Parameters: None
//Returns: The size of your vector as an integer
int size() const;
//Capacity function
//Purpose: Returns the capacity of the vector
//Parameters: None
//Returns: Maximum value that your vector can hold
int capacity() const;
//Clear function
//Purpose: Deletes all of the elements from the vector and resets its size to
// zero and its capacity to two; thus becoming empty
//Parameters: None
//Returns: None
void clear();
//push_back function
//Purpose: Adds the integer value n to the end of the vector
//Parameters: Takes a integer to be placed in the vector
//Returns: None
void push_back(const T& n)
{
//If statement to handle if array is full
if (numElements == cap)
{
//Doubling the capacity
cap = cap * VECTOR_CAP;
//Allocating new array
T* newVectorData = new T[cap];
//Copying data
for (int i = 0; i < numElements; i++) newVectorData[i] = vectorData[i];
//Deleting previous data
delete[] vectorData;
//Pointing to new data
vectorData = newVectorData;
}
//Storing data
vectorData[numElements++] = n;
}
//at function
//Purpose: Returns the value of the element at position n in the vector
//Parameters: None
//Returns: Returns your current place with the vector
T& at(std::size_t);
//assignment
//Purpose: Overload the = operator
//Parameters: The two myVector objects we want to assign
//Returns: The assignment
myVector operator=(const myVector&);
void pop_back();
int last();
T& operator[](std::size_t);
};
//Independant Functions
template <typename T>
myVector<T>::myVector()
{
//Setting the cap
cap = VECTOR_CAP;
//Creating the array
vectorData = new T[cap];
//Initializing the value
numElements = 0;
}
template <typename T>
myVector<T>::~myVector()
{
cap = 0;
//Delete array elements
delete[] vectorData;
//Allocate vectorData
vectorData = NULL;
}
template <typename T>
int myVector<T>::size() const
{
return numElements;
}
template <typename T>
void myVector<T>::pop_back()
{
numElements--;
}
template <typename T>
int myVector<T>::last()
{
return cap;
}
template <typename T>
int myVector<T>::capacity() const
{
return cap;
}
template <typename T>
T& myVector<T>::at(std::size_t n)
{
return vectorData[n];
}
template <typename T>
T& myVector<T>::operator[](std::size_t n)
{
return vectorData[n];
}
template <typename T>
myVector<T> myVector<T>::operator=(const myVector& rho)
{
//Test for assingment
if (this == &rho)
{
return *this;
}
//Delete lho
delete[] this->vectorData;
//Creating new array to fit rho data
cap = rho.cap;
this->vectorData = new int[cap];
//Copying data
for (int i = 0; i < numElements; i++)
{
this->vectorData[i] = rho.vectorData[i];
}
//Returning myVector object
return *this;
}
template <typename T>
std::ostream& operator<<(std::ostream& out, const myVector<T>& rho)
{
for (int n = 0; n < rho.size(); n++)
{
out << rho.at(n);
}
return out;
}

The last function should look like this:
template <typename T>
T myVector<T>::last()
{
return vectorData[numElements - 1];
}
A function that returns an element from the vector should have the return type the type of the vector elements, i.e. T in your case.
cout has different overloads for char and int. For char it prints the ASCII character of the code provided, for int it returns the code itself. So if your last element is Z and you return an int it would print the ASCII code of Z that is 90.
try this to get a sense of what I am saying:
cout << 'Z' << endl;
cout << (char) 'Z' << endl; // tautological cast as 'Z' is char
cout << (int) 'Z' << endl;
cout << 90 << endl;
cout << (int) 90 << endl; // tautological cast as 90 is int
cout << (char) 90 << endl;
As for pop_back all you have to do is:
if (numElements > 0)
numElements--;
Reason: there is no such thing as deleting memory. A cell of memory always has a value (be it one you set, 0, 1 or garbage). All you have to do is mark it as being available (or not used). That's what you do when you shrink numElements.
If you want to go a step further you could do the opposite of push_back, i.e. relocate the whole vector to a smaller allocated buffer. But this is not advised as these operations (allocating, copying) are expensive and you can do without them (unlike pus_back where you have to get a bigger size)

Related

Is an isFull() function for a Dynamic Array Container Class needed?

I'm having a bit of trouble wrapping this around my head; I used the debugger in VS to go through my code. I realized that when I call the insertBack() function in main() the elements aren't inserted since the condition if (!isFull) isn't met--returning false causing the insertion to not happen. I tried removing the condition and got some errors regarding my code trying to insert a number into an invalid portion of the array. While going through this, I started to ask myself is the isFull() function required since a dynamic array can be resized; but, how can it be full if this is the case? I looked a bit into vectors on cpprefrence and didn't find an isFull() member function.
#include <iostream>
template<typename T>
class container
{
template <typename T2>
friend std::ostream& operator<<(std::ostream& out, const container<T2> &cobj);
// Postcondition: contents of the container object cobj is displayed
public:
container();
// Postcondition: an empty container object is created with data members arr set to NULL, n set to -1 and Capacity set to 0
~container();
// Destructor; required as one of the Big-3 (or Big(5) because of the presence of a pointer data member. Default version results in
// memory leak!
// Postcondition: dynamic memory pointed to by arr has been release back to the “heap” and arr set to NULL or nullptr
// In order to see the action, message "destructor called and dynamic memory released!" is displayed
bool isEmpty() const;
// Postcondition: returns true is nothing is stored; returns false otherwise
bool isFull() const;
// Postcondition: returns true if arr array is filled to capacity; returns false otherwise
int size() const;
// Postcondition: returns the size or the number of elements (values) currently stored in the container
int capacity() const;
// Postcondition: returns the current storage capacity of the container
bool insertBack(const T& val);
// Postcondition: if container is not full, newVal is inserted at the end of the array;
// otherwise, double the current capacity followed by the insertion
bool deleteBack();
// Precondition: The array must not be empty
// Postcondition: the last element stored in the array is removed! size of the container is decremented by 1, capacity unchanged
void clear();
// Postcondition: all elements in arr of calling container object are cleared and the dynamic memory is released back to “heap”
private:
void allocate(T* &temp);
// Postcondition: if Capacity = 0, allocate a single location; otherwise the current capacity is doubled
T *arr;
int Capacity; // Note: Capital 'C' as capacity is used as a function name
int n; // size or actual # of values currently stored in the container; n <= SIZE
};
template<typename T2>
std::ostream& operator<<(std::ostream& out, const container<T2> &cobj)
{
std::cout << "Currently it contains " << cobj.size() << " value(s)" << std::endl
<< "Container storage capacity = " << cobj.capacity() << std::endl
<< "The contents of the container:" << std::endl;
if (cobj.isEmpty())
{
std::cout << "*** Container is currently empty!" << std::endl;
}
else
{
for (int i=0; i<cobj.size(); ++i)
{
std::cout << cobj.arr[i];
}
}
return out;
}
template<typename T>
container<T>::container()
{
arr = nullptr;
Capacity = 0;
n = 0;
}
template<typename T>
container<T>::~container()
{
delete arr;
arr = nullptr;
std::cout << "Destructor called! (this line is normally not displayed)" << std::endl;
}
template<typename T>
bool container<T>::isEmpty() const
{
return n==0;
}
template<typename T>
bool container<T>::isFull() const
{
return n==Capacity;
}
template<typename T>
int container<T>::capacity() const
{
return Capacity;
}
template<typename T>
int container<T>::size() const
{
return n;
}
template<typename T>
bool container<T>::insertBack(const T& val)
{
if (!isFull())
{
n++;
arr[n-1] = val;
return true;
}
else
{
return false;
}
}
template<typename T>
bool container<T>::deleteBack()
{
if (!isEmpty())
{
n--;
return true;
}
else
{
return false;
}
}
template<typename T>
void container<T>::clear()
{
if (!isEmpty())
{
n = 0;
return true;
}
else
{
return false;
}
}
template<typename T>
void container<T>::allocate(T* &temp)
{
if (Capacity==0)
{
temp = new T;
}
else
{
return Capacity*2;
}
}
int main()
{
container<int> a1;
std::cout << a1 << std::endl;
std::cout << "Currently, the container object contains 0 element(s) or 0 value(s)" << std::endl;
std::cout << "\nWe now insert 3 values at the back of the array, one at a time:" << std::endl;
const int num = 3;
for (int i=0, c=0; i<=num; ++i, c+=10)
{
a1.insertBack(c);
}
std::cout << a1;
}
I think that having an isFull method does not make sense, since your dynamic container is not limited in capacity. Instead, you can use the size and capacity methods to track the state of the container.
If you want to implement a vector and want to check if size smaller than or equals to capacity, then decide whether to resize it, you can wrapper size > = capacity as a private isFull() function. But I think it makes no sense to set it public.

Create a C++ template class which can work like a Vector of Vectors

This is a Group class, similar to a Vector. I can create a Vector of Groups and that works fine. I'm having difficulty creating a Groups of Groups. This code compiles and runs but the Group of Groups is not behaving in the same way to a Vector of Groups - see the output. I feel that I'm missing a special constructor in Group which handles templated types? Perhaps it's something else - any pointers gratefully received.
#include <vector>
template <class T>
class Group
{
private:
T *data;
int current_size;
int max_size;
private:
void expand();
public:
Group();
Group(int size);
~Group();
T operator[](int index) const;
int count() const;
int add_item(const T new_item);
};
template <class T>
Group<T>::Group()
{
data = NULL;
max_size = 0;
current_size = 0;
}
template <class T>
Group<T>::Group(int size)
{
if (size < 2)
size = 2;
data = new T[size];
max_size = size;
current_size = 0;
}
template <class T>
Group<T>::~Group()
{
if (data != NULL)
delete[] data;
current_size = 0;
max_size = 0;
}
template <class T>
void Group<T>::expand()
{
if (data == NULL)
{
current_size = 0;
max_size = 2;
data = new T[2];
}
else
{
// printf("expanding %x from %d to %d\n", this, current_size, current_size*2);
T *tempArray = new T[max_size * 2];
for (int i = 0; i < max_size; i++)
{
tempArray[i] = data[i];
}
delete[] data;
data = tempArray;
max_size = max_size * 2;
}
}
template <class T>
int Group<T>::add_item(const T new_item)
{
// expand the array if necessary
while (current_size >= (max_size))
expand();
// add_item the new thing
data[current_size] = new_item;
current_size++;
return (current_size);
}
template <class T>
inline T Group<T>::operator[](int index) const
{
return data[index];
}
template <class T>
inline int Group<T>::count() const
{
return current_size;
}
int main()
{
// Vector of Groups works fine
int numgroups = 3; // just 3 groups for testing
// a vector of Groups
std::vector<Group<int>> setofgroups(numgroups);
printf("setofgroups count=%d\n", setofgroups.size());
// some test data
// 4 items in first group
setofgroups[0].add_item(6);
setofgroups[0].add_item(9);
setofgroups[0].add_item(15);
setofgroups[0].add_item(18);
// one item in second
setofgroups[1].add_item(7);
// two items in third
setofgroups[2].add_item(8);
setofgroups[2].add_item(25);
// for each group, print the member values
for (int g = 0; g < setofgroups.size(); g++)
{
printf("group %d\n", g);
for (int i = 0; i < setofgroups[g].count(); i++)
printf(" member %d, value %d\n", i, setofgroups[g][i]);
}
// Group of groups doesn't seem to work
Group<Group<int>> groupofgroups(numgroups);
// this returns ZERO - not 3 as I expected
printf("groupofgroups count=%d\n", groupofgroups.count());
groupofgroups[0].add_item(6);
groupofgroups[0].add_item(9);
groupofgroups[0].add_item(15);
groupofgroups[0].add_item(18);
printf("groupofgroups[0].count=%d\n", groupofgroups[0].count()); // this returns ZERO - where did the items go?
groupofgroups[1].add_item(7);
// two items in third
groupofgroups[2].add_item(8);
groupofgroups[2].add_item(25);
// for each group, print the member values
for (int g = 0; g < groupofgroups.count(); g++)
{
printf("group 2 %d (count=%d)\n", g, groupofgroups[g].count());
for (int i = 0; i < groupofgroups[g].count(); i++)
printf(" member %d, value %d\n", i, groupofgroups[g][i]);
}
return 0;
}
Output:
setofgroups count=3
group 0
member 0, value 6
member 1, value 9
member 2, value 15
member 3, value 18
group 1
member 0, value 7
group 2
member 0, value 8
member 1, value 25
groupofgroups count=0
groupofgroups[0].count=0
There are 2 things to fix:
as suggested in the comment you need to set the current_size in the constructor
you need to return a reference with you operator[] else all modification will be applied to a temporary copy of the element
link to the code
You have a non trivial destructor in you class. That means that the default copy constructor and default copy assignment will make the wrong thing.
Here is a simple example:
Group<int> a(4); // ok, ready to add some elements in the freshly allocated a.data
a.add_item(1);
int count = a.add_item(2); // ok a contains 2 items 1 and 2
if (count == 2) {
Group<int> b = a; // the default copy ctor make b.data == a.data...
std::cout << "b contains " << b.count() << " items" << std::endl; // nice up to here
} // horror: b reaches end of life and destructor calls delete[](b.data) !
// a.data is now a dangling pointer...
So you have to either implement the copy constructor and the copy assignment operator or mark them explicitely deleted - that is the rule of 3 (more details here)
If you do not implement them, the compiler will implicitely provide a move ctor and a move assignment operator that do not work much greater than the copy version. So you must implement them or mark them explicitely deleted - that is the rule of 5.
And the recommended operator [] for containers - what standard library ones use - is:
T& operator[] (size_t index); // used for a[i] = ...
const T& operator[] (size_t index) const; // used for x = a[i];
Using references may avoid unnecessary copies of large objects...

Writing a vector class c++

So I'm trying to write a vector class which can take objects without a default constructor. To do so I'm using an array of raw pointers. Thing is, when I'm instantiating a new vector, let's call it 2, based upon a previous vector, let's call it 1-- it points to the underlying address of said previous object, 1. So when I insert a new value into 1, 2 is updated as well.
#ifndef MYVECTOR_MYVECTOR_H
#define MYVECTOR_MYVECTOR_H
#include <sstream>
#include <stdexcept>
#include <memory>
#include <vector>
#include <ostream>
template<typename T>
class MyVector;
template<typename T>
std::ostream& operator<<(std::ostream& out, const MyVector<T>& myVec){
out << "{";
for(int i = 0; i < myVec.numElem; i++){
out << &myVec.elements[i] << " ";
}
out << "}";
return out;
}
template<typename T>
class MyVector{
public:
int numElem;
int capacity;
T** elements;
MyVector(const unsigned int& numElements, const T& value) : numElem(numElements), capacity(numElements * 2){
elements = new T*[capacity];
for(int i = 0; i < numElem; i++){
elements[i] = new T(value);
}
}
template<typename U>
MyVector(const std::vector<U>& values): numElem(values.size()), capacity(values.size() * 2){
elements = new T*[capacity];
for(int i = 0; i < numElem; i++){
elements[i] = new T(values[i]);
}
}
void insert(const unsigned& pos, const T& value){
elements[numElem] = new T(*elements[numElem - 1]);
numElem++;
for(unsigned int i = numElem - 1; i > pos; i--){
elements[i] = elements[i - 1];
}
elements[pos] = new T(value);
}
};
#endif
Per comment #1:
class NoDefault {
public:
NoDefault(const int& value) : value(value) {}
int value;
};
std::ostream& operator<<(std::ostream& out, const NoDefault& noDefault) {
out << noDefault.value;
return out;
}
int main() {
MyVector<NoDefault> noDefaultVec(std::vector<NoDefault>{7,8,9,10,11});
MyVector<MyVector<NoDefault>> vecvec(2, noDefaultVec);
std::cout << "noDefaultVec = " << noDefaultVec << std::endl;
std::cout << "vecvec = " << vecvec << std::endl;
noDefaultVec.insert(3, 99);
vecvec.insert(1, noDefaultVec);
std::cout << "noDefaultVec = " << noDefaultVec << std::endl;
std::cout << "vecvec = " << vecvec << std::endl;
return 0;
}
You perform a shallow copy instead of a deep copy.
A shallow copy of your vector creates a new collection which shares elements with an old one. What follows, any change made to the original object will cause a change in a new one. What you need in that case is a deep copy, which duplicates every element from the source to the destination. After performing such a copy you are left with two vectors with seperate set of data.
Providing a copy constructor for your class solves the problem, but you should also remember about implementing destructor and assignment operator, basing on The Rule Of Three. You can also consider adding move constructor and move assignment operator (or one assignment operator following copy-and-swap idiom).

Segmentation Fault when Overloading addition operator and dynamic vectors

I'm trying to overload the addition operator but I keep getting a segmentation fault even though I'm passing in the argument by value after it's memory has been deallocated. Anybody have any idea what I could be doing wrong. Also once I get this running properly after fixing the overloaded addition, I need to use vectors instead of pointing to arrays which I have no idea how to declare in a manner equivalent to what I've wrritten for arrays.
RowAray.h
#ifndef ROWARAY_H // if constant ROWARAY_H not defined do not execute
#define ROWARAY_H // defines constant ROWARAY_H
#include <new> // Needed for bad_alloc exception
#include <cstdlib> // Needed for the exit function
template <class T>
class RowAray{
private:
int size;
T *rowData;
void memError(); // Handles memory allocation errors
void subError(); // Handles subscripts out of range
public:
RowAray(T); //used to construct row Array object
~RowAray(){delete [] rowData;} //used to deallocate dynamically allocated memory from Row array
int getSize(){return size;} //inline accessor member function used to return length of Row array
void setData(int row, T value);
T getData(int i){return (( i >=0&& i < size)?rowData[i]:0);} //
T &operator[](const int &);
};
template <class T>
RowAray<T>::RowAray(T colSize){
size =colSize>1?colSize:1;
// Allocate memory for the array.
try
{
rowData = new T [size];
}
catch (bad_alloc)
{
memError();
}
// Initialize the array.
for (int count = 0; count < size; count++){
T value = rand()%90+10;
setData(count, value);
}
}
template <class T>
void RowAray<T>::memError()
{
cout << "ERROR:Cannot allocate memory.\n";
exit(EXIT_FAILURE);
}
template <class T>
void RowAray<T>::subError()
{
cout << "ERROR: Subscript out of range.\n";
exit(EXIT_FAILURE);
}
template <class T>
T &RowAray<T>::operator[](const int &sub)
{
if (sub < 0 || sub >= size)
subError();
else
return rowData[sub];
}
template <class T>
void RowAray<T>::setData(int row, T value){
//used to fill array with random 2 digit #s
*(rowData + row) = value;
}
#endif /* ROWARAY_H */
Table.h
#ifndef TABLE_H
#define TABLE_H
#include "RowAray.h"
template <class T>
class Table{
private:
int szRow;
int szCol;
RowAray<T> **records;
public:
Table(int,int); //used to construct Table object
Table(const Table &);
~Table(); //used to deallocate dynamically allocated memory from Table object
int getSzRow() const{return szRow;} //used to return row size
int getSzCol()const {return szCol;}
Table operator+(const Table &);
T getRec(int, int) const; //used to return inserted random numbers of 2d arrays
};
template <class T>
Table<T>::Table(int r, int c ){
//Set the row size
this->szRow = r;
//Declare the record array
records = new RowAray<T>*[this->szRow];
//Size each row
this->szCol = c;
//Create the record arrays
for(int i=0;i<this->szRow;i++){
records[i]=new RowAray<T>(this->szCol);
}
}
template <class T>
Table<T>::Table(const Table &Tab){
szRow=Tab.getSzRow();
szCol=Tab.getSzCol();
records = new RowAray<T>*[szCol];
for(int i = 0; i < this->szCol; i++){
records[i] = new RowAray<T>(szRow);
}
//set elements = to random value
for(int row = 0; row < szRow; row++){
for(int col = 0; col < this->szCol; col++){
int value = Tab.getRec(row, col);
records[col]->setData(row,value);
}
}
}
template <class T>
T Table<T>::getRec(int row, int col) const{
//if else statement used to return randomly generated numbers of array
if(row >= 0 && row < this->szRow && col >= 0 && col < this->szCol){
return records[row]->getData(row);
}else{
return 0;
}
}
template <class T>
Table<T>::~Table(){
//Delete each record
for(int i=0;i<this->szRow;i++){
delete records[i];
}
delete []records;
}
template <class T>
Table<T> Table<T>::operator+(const Table &Tab){
Table temp(Tab.getSzRow(), Tab.getSzCol());
//set elements = to random value for operation to
for(int row=0; row < szRow; row++){
for(int col=0; col < szCol; col++){
int value = getRec(row, col) + Tab.getRec(row, col);
temp.records[col]->setData(row,value);
}
}
return temp;
}
#endif /* TABLE_H */
main.cpp
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <iomanip>
using namespace std;
//User Libraries
#include "Table.h"
//Global Constants
//Function Prototype
template<class T>
void prntRow(T *,int);
template<class T>
void prntTab(const Table<T> &);
//Execution Begins Here!
int main(int argc, char** argv) {
//Initialize the random seed
srand(static_cast<unsigned int>(time(0)));
//Declare Variables
int rows=3,cols=4;
//Test out the Row with integers and floats
RowAray<int> a(3);
RowAray<float> b(4);
cout<<"Test the Integer Row "<<endl;
prntRow(&a,3);
cout<<"Test the Float Row "<<endl;
prntRow(&b,4);
//Test out the Table with a float
Table<float> tab1(rows,cols);
Table<float> tab2(tab1);
Table<float> tab3 = tab1 + tab2;
cout<<"Float Table 3 size is [row,col] = Table 1 + Table 2 ["
<<rows<<","<<cols<<"]";
prntTab(tab3);
//Exit Stage Right
return 0;
}
template<class T>
void prntRow(T *a,int perLine){
cout<<fixed<<setprecision(1)<<showpoint<<endl;
for(int i=0;i<a->getSize();i++){
cout<<a->getData(i)<<" ";
if(i%perLine==(perLine-1))cout<<endl;
}
cout<<endl;
}
template<class T>
void prntTab(const Table<T> &a){
cout<<fixed<<setprecision(1)<<showpoint<<endl;
for(int row=0;row<a.getSzRow();row++){
for(int col=0;col<a.getSzCol();col++){
cout<<setw(8)<<a.getRec(row,col);
}
cout<<endl;
}
cout<<endl;
}
You error stems from line 85 of Table.h, in you + operator overload:
temp.records[col]->setData(row,value);
should really be
temp.records[row]->setData(col,value);
Apart from that, I spotted another error in the same file in line 62 (method Table<T>::getRec(int row, int col)):
return records[row]->getData(row);
should be
return records[row]->getData(col);
Apart from those problems, I would highly advise you to rethink and restructure your code (maybe you could also try a code review), since a large part of it is superfluous in my opinion and some things could become problematic if you expand the project (for example, RowAray's constructor takes a T colSize as parameter where you should probably use an int or, better, a size_t. This code as it is will not work when T is not implicitly convertible to an integer type).

Cannot convert argument 'int' to 'char &'

I am receiving a compiler error that I don't understand, and don't know how to deal with it properly. If anyone could offer me some advice on how to fix it I would be much appreciated. The error reads:
Error 1 error C2664: 'char myVector<char>::at(T &) const' : cannot convert argument 1 from 'int' to 'char &'
It's on line 159 of the header code where it reads out << rho.at(n);.
Driver:
#include <iostream>
#include "vectorHeader.h"
using namespace std;
int main()
{
const char START = 'A';
const int MAX = 12;
// create a vector of doubles
myVector<char> vectD;
// push some values into the vector
for (int i = 0; i < MAX; i++)
{
vectD.push_back(START + i);
}
// remove the last element
vectD.pop_back();
// add another value
vectD.push_back('Z');
// test memory management
myVector<char> vectD2 = vectD;
// display the contents
cout << "\n[";
for (int i = 0; i < vectD2.size() - 1; i++)
{
cout << vectD2[i] << ", ";
}
cout << "..., " << vectD2.last() << "]\n";
system("PAUSE");
return 0;
}
Header:
#include <iostream>
#include <iomanip>
#include <string>
#include <vector>
#include <fstream>
#include <stdexcept>
//Declaring constant
const int VECTOR_CAP = 2;
template <class T>
class myVector
{
private:
//Setting data members
T* vectorData;
int cap;
int numElements;
public:
//Default constructor
//Purpose: Creates a vector
//Parameters: None
//Returns: None
myVector();
//Parameterized constructor
//Purpose: Creates a vector capacity of n
//Parameters: None
//Returns: None
myVector(const T&);
//Copy Constructor
//Purpose: Copy data into vector
//Parameters: myVector object
//Returns: None
myVector(const myVector& copy)
{
numElements = copy.numElements;
vectorData = new T [numElements];
for (int i = 0; i < numElements; i++)
{
this->vectorData[i] = copy.vectorData[i];
}
}
//Destructor
//Purpose:Deletes any dynamically allocated storage
//Parameters: None
//Returns: None
~myVector();
//Size function
//Purpose: returns the size of your vector
//Parameters: None
//Returns: The size of your vector as an integer
int size() const;
//Capacity function
//Purpose: Returns the capacity of the vector
//Parameters: None
//Returns: Maximum value that your vector can hold
int capacity() const;
//Clear function
//Purpose: Deletes all of the elements from the vector and resets its size to zero
// and its capacity to two; thus becoming empty
//Parameters: None
//Returns: None
void clear();
//push_back function
//Purpose: Adds the integer value n to the end of the vector
//Parameters: Takes a integer to be placed in the vector
//Returns: None
void push_back(const T& n)
{
//If statement to handle if array is full
if (numElements == cap)
{
//Doubling the capacity
cap = cap * VECTOR_CAP;
//Allocating new array
T* newVectorData = new T[cap];
//Copying data
for (int i = 0; i < numElements; i++) newVectorData[i] = vectorData[i];
//Deleting previous data
delete[] vectorData;
//Pointing to new data
vectorData = newVectorData;
}
//Storing data
vectorData[numElements++] = n;
}
//at function
//Purpose: Returns the value of the element at position n in the vector
//Parameters: None
//Returns: Returns your current place with the vector
T at(T&) const;
//assignment
//Purpose: Overload the = operator
//Parameters: The two myVector objects we want to assign
//Returns: The assignment
myVector operator=(const myVector&);
void pop_back();
int last();
myVector operator[](const myVector&);
};
//Independant Functions
template <typename T>
int myVector<T>::capacity() const
{
return cap;
}
template <typename T>
myVector<T> myVector<T>::operator=(const myVector& rho)
{
//Test for assingment
if (this == &rho)
{
return *this;
}
//Delete lho
delete[] this->vectorData;
//Creating new array to fit rho data
cap = rho.cap;
this->vectorData = new int[cap];
//Copying data
for (int i = 0; i < numElements; i++)
{
this->vectorData[i] = rho.vectorData[i];
}
//Returning myVector object
return *this;
}
template <typename T>
std::ostream& operator<<(std::ostream& out, const myVector<T>& rho)
{
for (int n = 0; n < rho.size(); n++)
{
out << rho.at(n);
}
return out;
}
Exactly what it says on the tin. When you have
T at(T&) const;
in a myVector<char>, that translates to
char at(char&) const;
and an int cannot be bound to a reference to char. I think you meant to say
T at(int) const;
or, better,
T at(std::size_t) const;
because std::size_t is usually (by convention) used for this sort of thing. int is implicitly convertible to std::size_t, so that will also just work.
Your declaration of myVector::at(T&) takes the templated type as an argument. You need to declare it as
T at(unsigned int&) const
That way you can use the parameter as an index.