It has been more than a decade since the last time I wrote something in C/C++ and now I have a problem I cannot solve. Basically I have two classes, say CA and CB, where CA looks like a vector and CB looks like a two-dimensional matrix.
The issue that I am facing is that I want to construct an object of type CB and do so by using another object of type CB. Therefore, I pass as a parameter an object of type CB that has been initialized correctly, but when I do that, I get an error of the form ./B.h:97:43: error: no viable overloaded operator[] for type 'const CB<double>'.
The way I copy the object is by relying on the copying mechanism for class CA. Having said that, constructing an object of class CA by using another initialized object of class CA appears to be working fine. So, I am a little bit lost as to what is wrong. I also get additional help from the compiler for my error, but I am not sure how to fix things really. The full error that I receive using g++ is the following:
In file included from main.cpp:1:
./B.h:97:43: error: no viable overloaded operator[] for type 'const CB<double>'
(*theRows)[i] = new CA <DataType>(m[i]);
^ ~
./B.h:105:2: note: in instantiation of member function 'CB<double>::copy' requested here
copy(a);
^
main.cpp:24:16: note: in instantiation of member function 'CB<double>::CB' requested here
CB<double> myPrecious(mycb_c);
^
./B.h:21:27: note: candidate function not viable: 'this' argument has type 'const CB<double>', but method is not marked const
virtual CA<DataType>& operator[] (int index);
^
1 error generated.
There must be something that I do not remember how to do, or most likely, I am not aware of. Note that if you comment the offending line fromm main.cpp (line 24) with the command CB<double> myPrecious(mycb_c);, then the program compiles without a problem and the output is fine.
I tried to create a minimal example and this is as far as I could shrink the code.
Any ideas on how to make the constructor work by using copy? I appreciate your time.
BELOW ARE THE FILES
main.cpp:
#include "B.h"
int main()
{
CA<double> myca_a(3);
CA<double> myca_b(myca_a);
CB<double> mycb_c(2, 3, 3.0);
CB<double> mycb_d(3, 2, 4.0);
CB<double> mycb_e;
cout << "<separator>" << endl;
cout << myca_a << endl;
cout << "<separator>" << endl;
cout << myca_b << endl;
cout << "<separator>" << endl;
cout << mycb_c << endl;
cout << "<separator>" << endl;
cout << mycb_d << endl;
cout << "<separator>" << endl;
cout << mycb_e << endl;
cout << "<separator>" << endl;
CB<double> myPrecious(mycb_c);
return 0;
}
A.h:
#include <iostream>
using namespace std;
template <class DataType>
class CA
{
protected:
DataType* paDataType;
int _size;
void copy(const CA<DataType>& ac);
public:
CA();
CA(int n);
CA(int n, const DataType& o);
CA(const CA<DataType>& ac);
virtual ~CA();
int size() const;
DataType& operator [] (int k);
void operator= (const CA<DataType>& ac);
friend ostream& operator<<(ostream& os, CA<DataType>& a) {
os << "[";
for (int i = 0; i < a.size() - 1; i++)
os << a[i] << " ";
os << a[a.size() - 1] << "]";
return os;
}
};
//Empty constructor
template <class DataType>
CA<DataType>::CA()
{
paDataType = new DataType[1];
_size = 1;
}
//Constructor
template <class DataType>
CA<DataType>::CA(int n)
{
paDataType = new DataType[n];
_size = n;
}
//Constructor w/ value
template <class DataType>
CA<DataType>::CA(int n, const DataType& o)
{
paDataType = new DataType[n];
_size = n;
for (int i = 0; i < _size; i++) paDataType[i] = o;
}
//Copy Constructor
template <class DataType>
CA<DataType>::CA(const CA<DataType>& ac)
{
copy(ac);
}
//Copy method
template <class DataType>
void CA<DataType>::copy(const CA<DataType>& ac)
{
paDataType = new DataType[ac._size];
_size = ac._size;
for (int i = 0; i < _size; i++)
paDataType[i] = ac.paDataType[i];
}
//Destructor
template<class DataType>
CA<DataType>::~CA()
{
if (paDataType != NULL)
delete[] paDataType;
paDataType = NULL;
_size = 0;
}
//Size method
template <class DataType>
int CA<DataType>::size() const
{
return _size;
}
//Accessor
template <class DataType>
DataType& CA<DataType>::operator [] (int k)
{
return paDataType[k];
}
//Overloaded assignment operator
template <class DataType>
void CA<DataType>::operator= (const CA<DataType>& ac)
{
if (paDataType != NULL) delete[] paDataType;
copy(ac);
}
B.h:
#include "A.h"
template <class DataType>
class CB : public CA <CA <DataType> >
{
protected:
CA < CA<DataType>* >* theRows;
void copy(const CB<DataType>& m);
void deleteRows();
public:
CB();
CB(int n, int m);
CB(int n, int m, DataType v);
CB(const CB& a);
virtual ~CB();
void operator= (const CB<DataType>& a);
virtual int size() const;
int columns();
int rows();
virtual CA<DataType>& operator[] (int index);
friend ostream& operator<<(ostream& os, CB<DataType>& m) {
int rows = m.rows();
int cols = m.columns();
os << "----------" << endl;
for (int i = 0; i < rows-1; i++) {
for (int j = 0; j < cols-1; j++) {
os << m[i][j] << " ";
}
os << m[i][cols-1] << endl;
}
for (int j = 0; j < cols-1; j++) {
os << m[rows-1][j] << " ";
}
os << m[rows-1][cols-1] << endl;
os << "----------";
return os;
}
};
template <class DataType> CB<DataType>::CB() {
theRows = new CA <CA <DataType>* >(1, NULL);
(*theRows)[0] = new CA <DataType>();
}
template <class DataType>
CB<DataType>::CB(int n, int m)
{
theRows = new CA <CA <DataType>* >(n, NULL);
for (int i = 0; i < n; i++)
{
(*theRows)[i] = NULL;
(*theRows)[i] = new CA <DataType>(m);
}
}
template <class DataType>
CB<DataType>::CB(int n, int m, DataType v)
{
theRows = new CA <CA <DataType>* >(n, NULL);
for (int i = 0; i < n; i++)
{
(*theRows)[i] = new CA <DataType>(m, v);
}
}
template <class DataType>
void CB<DataType>::deleteRows()
{
if (theRows != NULL)
{
for (int i = 0; i < theRows->size(); i++)
{
if ((*theRows)[i] != NULL) delete (*theRows)[i];
(*theRows)[i] = NULL;
}
delete theRows;
}
theRows = NULL;
}
template <class DataType>
CB<DataType>::~CB()
{
deleteRows();
}
template <class DataType>
void CB<DataType>::copy(const CB<DataType>& m)
{
deleteRows();
theRows = new CA <CA <DataType>* >(m.size(), NULL);
for (int i = 0; i < m.size(); i++)
{
(*theRows)[i] = new CA <DataType>(m[i]);
}
}
template <class DataType>
CB<DataType>::CB(const CB<DataType>& a)
{
deleteRows();
copy(a);
}
template <class DataType>
void CB<DataType>::operator= (const CB<DataType>& a)
{
copy(a);
}
template <class DataType>
int CB<DataType>::size() const
{
return theRows->size();
}
template <class DataType>
CA<DataType>& CB<DataType>::operator[] (int index)
{
return (*(*theRows)[index]);
}
template <class DataType>
int CB<DataType>::rows()
{
return theRows->size();
}
template <class DataType>
int CB<DataType>::columns()
{
return (*this)[0].size();
}
The problem is that currently you have overloaded operator[] as a non-const member function of class template CB. This means that the implicit this parameter of this member function is of type CB<DataType>*. Meaning that we can use this member function only with non-const objects.
To solve this problem you need to make it(overload it as) a const member function instead by adding a const as shown below, so that now the implicit this parameter will be of type const CB<DataType>* meaning now it can be used with const objects.
template <class DataType>
class CB : public CA <CA <DataType> >
{
virtual CA<DataType>& operator[] (int index) const; //added const here
//other members here
}
template <class DataType>
CA<DataType>& CB<DataType>::operator[] (int index) const //added const here
{
return (*(*theRows)[index]);
}
//other code here
The program compiles after the modification as can be seen here.
Related
Let me post my code first:
Set.h
#pragma once
#include <string>
template<class _type> class Set
{
public:
Set();
Set m_add(Set _set1, Set _set2);
void m_addElem(Set *const _set, _type _elem);
void m_deleteElem(Set *const _set, _type _elem);
void m_addArray(_type _arr[], int _size);
Set(Set &_coll);
void operator+(_type _num);
void operator+(_type _elem[]);
Set operator+(Set *const _set);
void operator-(_type _num);
Set & operator=(Set &_set);
void m_display();
int m_check(_type elem);
~Set(void);
private:
_type * m_pelements;
int m_setSize;
};
Set.cpp
#pragma warning( disable : 4996 )
#include "Set.h"
#include <iostream>
#include <string>
template <class _type>
Set<_type>::Set()
{
m_setSize = 0;
}
template <class _type>
Set<_type>::Set(Set<_type> &_coll)
{
m_setSize = _coll.m_setSize;
m_pelements = new _type[_coll.m_setSize];
for (int i = 0;i<m_setSize;i++)
{
m_pelements[i] = _coll.m_pelements[i];
}
}
template <class _type>
Set<_type>::~Set()
{
delete [] m_pelements;
}
template <class _type>
Set<_type> Set<_type>::m_add(Set<_type> _set1, Set<_type> _set2)
{
Set<_type> finalSet;
finalSet = _set1;
for (int i = 0;i<_set2->m_setSize;i++)
{
m_addElem(finalSet, _set2->m_pelements[i]);
}
return finalSet;
}
template <class _type>
void Set<_type>::m_addElem(Set<_type> *const _set, _type _elem)
{
if (_set->m_setSize == 0)
{
_set->m_pelements = new _type[1];
_set->m_pelements[0] = _elem;
_set->m_setSize += 1;
}
else
{
_set->m_setSize += 1;
_type * helpElements = new _type[_set->m_setSize];
std::copy(_set->m_pelements, _set->m_pelements + _set->m_setSize-1, helpElements);
helpElements[_set->m_setSize-1] = _elem;
delete [] _set->m_pelements;
_set->m_pelements = helpElements;
/*
_type * helpElements = new _type[_set->m_setSize];
for (int i = 0;i<_set->m_setSize;i++)
{
helpElements[i] = _set->m_pelements[i];
}
delete _set->m_pelements;
_set->m_setSize += 1;
_set->m_pelements = new _type[_set->m_setSize];
for (int i = 0;i<_set->m_setSize;i++)
{
_set->m_pelements[i] = helpElements[i];
}
_set->m_pelements[_set->m_setSize-1] = _elem;
*/
}
}
template <class _type>
void Set<_type>::m_deleteElem(Set<_type> *const _set, _type _elem)
{
int index = _set->m_check(_elem);
if (index >= 0)
{
int k = 0;
_set->m_setSize -= 1;
_type * temp = new _type[_set->m_setSize];
for (int i = 0;i<_set->m_setSize;i++)
{
if (i == index)
k++;
temp[i] = _set->m_pelements[i+k];
}
delete [] _set->m_pelements;
_set->m_pelements = temp;
}
}
template <class _type>
void Set<_type>::m_addArray(_type _elem[], int size)
{
for (int i = 0;i<size;i++)
{
m_addElem(this,_elem[i]);
}
}
template <class _type>
void Set<_type>::operator+( _type _elem)
{
m_addElem(this,_elem);
}
template <class _type>
Set<_type> Set<_type>::operator+(Set<_type> *const _set)
{
return m_add(this,_set);
}
template <class _type>
void Set<_type>::operator+( _type _elem[])
{
m_addArray(this,_elem);
}
template <class _type>
void Set<_type>::operator-( _type _elem)
{
m_deleteElem(this,_elem);
}
template <class _type>
Set<_type> & Set<_type>::operator=(Set<_type> &_set)
{
if(&_set==this) return *this;
delete [] m_pelements;
m_setSize = _coll.m_setSize;
m_pelements = new _type[_coll.m_setSize];
for (int i = 0;i<m_setSize;i++)
{
m_pelements[i] = _coll.m_pelements[i];
}
}
template <class _type>
void Set<_type>::m_display()
{
for (int i = 0;i<m_setSize;i++)
{
std::cout << m_pelements[i] << " " ;
}
std::cout << std::endl;
}
template <class _type>
int Set<_type>::m_check(_type _elem)
{
for (int i = 0;i<m_setSize;i++)
{
if (m_pelements[i] == _elem)
return i;
}
return -1;
}
Main.cpp
#pragma warning( disable : 4996 )
#include "Set.h"
#include "Set.cpp"
#include <iostream>
int main()
{
Set<std::string> zbior1;
zbior1 + std::string("abc");
zbior1 + std::string("abcd");
zbior1 + std::string("abcdef");
zbior1 + std::string("XD");
zbior1.m_display();
zbior1 - "XD";
zbior1.m_display();
std::string tablica[3] = {"ala", "ma", "kota" };
zbior1.m_addArray(tablica,3);
zbior1.m_display();
Set<std::string> zbior2;
zbior2 + std::string("abDDc");
zbior2 + std::string("abcdDD");
zbior2 + std::string("abcdeDDf");
zbior2 + std::string("XDDD");
zbior2.m_display();
Set<std::string> zbior3;
zbior3 = zbior1 + zbior2; //HERE'S THE PROBLEM
}
Problem appears int the last line of Main.cpp
When arguments of Set operator+ are (Set *const _set) I get error " no operator found which takes a right-hand operand of type 'Set<_type>' (or there is no acceptable conversion)'" and if i remove *const there's different error saying "cannot convert parameter 1 from 'Set<_type> *const ' to 'Set<_type>'"
I have no idea how to repair it.
Your
Set operator+(Set *const _set);
is defined as taking a const pointer (which is for sure what you don't want), but you then pass to it an object instead, and not the address of an object. Pass by reference, like
Set operator+(Set const & _set);
Try reading Operator overloading for a very good introduction to the subject.
This method:
Set operator+(Set *const _set);
should probably look like:
Set operator+(Set const &rhs) const;
if it's going to stay a method. See the link in vsoftco's answer for why it should probably be a free non-friend function instead, implemented in terms of operator+=.
You pasted the same message for both errors, afaics, but at least one is complaining about the attempt to pass zbior2 to a method expecting a pointer.
I'm doing an assignment and I've put together a template class for a Vector, and now have inherited it (per the assignment) to make it a sort-able. At the very end of the void SearchableVector<T>::add(T itemToAdd) method it throws a Debug Assertion Failed! error. The full text of the error is as follows:
---------------------------
Microsoft Visual C++ Runtime Library
---------------------------
Debug Assertion Failed!
Program: ...tudio 2012\Projects\COSC 1437\Program 10\Debug\Program 10.exe
File: f:\dd\vctools\crt_bld\self_x86\crt\src\dbgdel.cpp
Line: 52
Expression: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)
For information on how your program can cause an assertion
failure, see the Visual C++ documentation on asserts.
(Press Retry to debug the application)
---------------------------
Abort Retry Ignore
---------------------------
I've looked around and I realize this is a pretty common error usually related to memory management. Often calling delete on inappropriate things. I must be doing something similar because I'm getting the error, but I cannot find what I'm doing wrong. If you could help me out and/or point me in the right direction that would be much appreciated.
Main.cpp
#include "SimpleVector.h"
#include "SearchableVector.h"
#include <stdlib.h>
#include <time.h>
void main()
{
srand (time(NULL));
SearchableVector<int> v(0);
for (int i = 0; i < 20; i++)
{
v.add(rand() % 20);
}
v.print();
}
SimpleVector.h
#ifndef SIMPLEVECTOR_H
#define SIMPLEVECTOR_H
#include <iostream>
#include <stdexcept>
#include <iomanip>
using namespace std;
template<class T>
class SimpleVector {
public:
//Constructors
SimpleVector(); //default constructor, size 0
SimpleVector(int); //parameterized constructor with default size
SimpleVector(const SimpleVector& a); //copy constructor
~SimpleVector(); //destructor
T& operator[](int) const;
SimpleVector<T>& operator=(SimpleVector<T>);
const bool operator==(SimpleVector&) const;
void push_back(T);
T& pop_back();
T& getElement(int);
int getSize() const;
void print() const;
protected:
int size;
T* internalArray;
void SimpleVector<T>::swap(SimpleVector&);
};
template<class T>
SimpleVector<T>::SimpleVector()
{
size = 0;
internalArray = nullptr;
}
template<class T>
SimpleVector<T>::SimpleVector(int sizeOfArray)
{
if (sizeOfArray < 0) throw "SimpleVector size must not be less than 0";
internalArray = new T[sizeOfArray]();
size = sizeOfArray;
}
template<class T>
SimpleVector<T>::SimpleVector(const SimpleVector& vectorToCopy):size(vectorToCopy.getSize()), internalArray( new T[vectorToCopy.getSize()] )
{
for (int i = 0; i < size; i++)
internalArray[i] = vectorToCopy.internalArray[i];
}
template<class T>
SimpleVector<T>::~SimpleVector() {
//cout << "Destructor called" << std::endl;
delete[] internalArray;
}
template<class T>
T& SimpleVector<T>::operator[](int i) const {
if (i<0 || i>=size) throw "Vector::operator[] : index is out of range";
return internalArray[i];
}
template<class T>
SimpleVector<T>& SimpleVector<T>::operator=(SimpleVector<T> rightSide) {
rightSide.swap(*this);
return *this;
}
template<class T>
const bool SimpleVector<T>::operator==(SimpleVector& right) const {
if (size() != right.size())
return false;
else {
for (int i = 0; i < size(); i++){
if (internalArray[i] != right[i])
return false;
}
}
return true;
}
template<class T>
void SimpleVector<T>::push_back(T itemToAdd) {
SimpleVector<T> temp(size + 1);
for (int i = 0; i < size; i++)
temp[i] = internalArray[i];
temp[size] = itemToAdd;
temp.swap(*this);
}
template<class T>
T& SimpleVector<T>::pop_back()
{
SimpleVector<T> temp(size - 1);
for (int i = 0; i < size; i++)
temp[i] = internalArray[i];
T pop = internalArray[size-a];
temp.swap(*this);
return pop;
}
template<class T>
T& SimpleVector<T>::getElement(int indexToGet)
{
return internalArray[indexToGet];
}
template<class T>
int SimpleVector<T>::getSize() const {
return this->size;
}
template<class T>
void SimpleVector<T>::print() const
{
for (int i = 0; i < size; i++)
{
std::cout << internalArray[i];
if (i!=(size-1))
std::cout << ",";
else
std::cout << std::endl;
if (i%10 == 0 && i!=0)
std::cout <<std::endl;
}
}
template<class T>
void SimpleVector<T>::swap(SimpleVector& other)
{
std::swap(internalArray, other.internalArray);
std::swap(size, other.size);
}
#endif
SearchableVector.h
#ifndef SEARCHABLEVECTOR_H
#define SEARCHABLEVECTOR_H
#include "SimpleVector.h"
template<class T>
class SearchableVector : protected SimpleVector<T>
{
public:
SearchableVector(int);
SearchableVector(const SearchableVector&);
~SearchableVector();
void add(T);
T getElement(int);
int getSize() const;
void print() const;
int search(T);
};
template<class T>
SearchableVector<T>::SearchableVector(int sizeOfArray) : SimpleVector(sizeOfArray)
{
}
template<class T>
SearchableVector<T>::SearchableVector(const SearchableVector& vectorToCopy) : SimpleVector(vectorToCopy)
{
}
template<class T>
SearchableVector<T>::~SearchableVector()
{
delete[] internalArray;
}
template<class T>
void SearchableVector<T>::add(T itemToAdd)
{
bool flag = false;
SearchableVector<T> temp(size + 1);
for (int i = 0; i < size; i++)
{
if ((itemToAdd <= internalArray[i]) && (flag == false))
{
temp[i] = itemToAdd;
i++;
flag = true;
}
temp[i] = internalArray[i];
}
if (flag == false)
temp[size] = itemToAdd;
temp.swap(*this);
} // !*******************! THROWS THE ERROR RIGHT HERE !*******************!
template<class T>
T SearchableVector<T>::getElement(int elementToGet)
{
return SimpleVector::getElement(elementToGet);
}
template<class T>
int SearchableVector<T>::getSize() const
{
return SimpleVector::getSize();
}
template<class T>
void SearchableVector<T>::print() const
{
SimpleVector::print();
}
template<class T>
int SearchableVector<T>::search(T itemToSearchFor)
{
}
#endif
First of all, when using inheritance, 99% of the time you should use a virtual destructor.
That's very important.
virtual ~SimpleVector();
When deleting an object, its base class destructor is called too.
And in your case you have delete[] internalArray; in both destructors.
Just leave that delete in the base class, because that member belongs to it, and it should take care of it.
Next time you encounter something like this, put a breakpoint near all the delete calls for that object type, then you can see which ones are called and in what order.
// stdafx.h
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//
#include "targetver.h"
#include <stdio.h>
#include <tchar.h>
#include <iostream>
using namespace std;
#include "Animal.h"
// TODO: reference additional headers your program requires here
class Animal
{
private:
int itsWeight;
public:
Animal(int);
Animal();
~Animal() {}
int getWeight() const { return itsWeight; }
void Display() const;
};
template <class T>
class Array
{
private:
T *pType;
int itsSize;
const int defaultSize = 10;
public:
//constructors
Array(int itsSize = defaultSize);
Array(const Array &rhs);
~Array() { delete[] pType; }
//operators
Array& operator=(const Array&);
T& operator[](int offSet){ return pType[offSet]; }
const T& operator[](int offSet) const { return pType[offSet]; }
//methods of Access
int getSize() const { return itsSize; }
};
//constructor
template <class T>
Array<T>::Array(int size) :
itsSize(size)
{
pType = new T[size];
for (int i = 0; i < size; i++)
{
pType[i] = 0;
}
}
//copy-constructor
template <class T>
Array<T>::Array(const Array &rhs)
{
itsSize = rhs.getSize();
pType = new T[itsSize];
for (int i = 0; i < itsSize; i++)
{
pType[i] = rhs[i];
}
}
//operator prisvoeniya
template <class T>
Array<T>& Array<T>::operator=(const Array &rhs)
{
if (this == &rhs)
return *this;
delete[] pType;
itsSize = rhs.getSize();
pType = new T[itsSize];
for (int i = 0; i < itsSize; i++)
{
pType[i] = rhs[i];
}
return *this;
}
//this is the file "Animal.cpp"
#include "stdafx.h"
#include "Animal.h"
Animal::Animal()
{
itsWeight = 0;
}
Animal::Animal(int weight)
{
itsWeight = weight;
}
void Animal::Display() const
{
cout << itsWeight;
}
// the main function
#include "stdafx.h"
int_tmain(int argc, _TCHAR* argv[])
{
Array<int> theArray; //Integer array
Array<Animal> theZoo; //Animal array
Animal *pAnimal;
//filling the array
for (int i = 0; i < theArray.getSize(); i++)
{
theArray[i] = i * 2;
pAnimal = new Animal[i * 3];
theZoo[i] = *pAnimal;
delete pAnimal;
}
for (int j = 0; j < theArray.getSize(); j++)
{
cout << "theArray[" << j << "]:\t";
cout << theArray[j]<<"\t\t";
cout << "theZoo[" << j << "]:\t";
theZoo[j].Display();
cout << endl;
}
return 0;
}
The problem is that: The compiler gives me the errors
Error 1 error C2648: 'Array<int>::defaultSize' : use of member as default parameter requires static member
d:\documents\work\c++ files\tigrans\homework10\templates\templates\templates\animal.h 28 1 Templates
Error 2 error C2648: 'Array<Animal>::defaultSize' : use of member as default parameter requires static member
d:\documents\work\c++ files\tigrans\homework10\templates\templates\templates\animal.h 28 1 Templates
Anybody can help me to understand that. I change the
const int defaultSize=10;
to
static const int defaultSize=10
then there is not errors but in that time show Debug Assertion Failed!
This part of your code is dodgy
{
pAnimal = new Animal[i * 3];
theZoo[i] = *pAnimal;
delete pAnimal;
}
The first line allocates an array of i*3 Animals, using their default constructor (which makes an Animal with itsWeight=0). In the second line you assign the first these newly allocated Animals to theZoo[i]. Finally, the third line tries to de-allocate the Animals.
The last line contains an error, since you call delete on a pointer obtained with new [].
The whole concept of creating objects on the heap only to immediately destroy them is quite dubious -- perhaps you come from another programming language, where this is the only way to create things? First, you could simply use an automatic variable
{
Animal a; // or a(i*3);
theZoo[i] = a;
}
or yet briefer
{
theZoo[i] = Animal(i*3);
}
(Note the if you would use a std container, you could say theZoo.emplace_back(i*3);, avoiding the copy of Animal.)
Long-time reader, first-time poster!
A few comments before I begin: I'm not looking for anyone to do my work for me, I just need a little guidance. Also, I've done a decent amount of googling, and I haven't been able to find any solutions yet.
I have a class assignment that involves creating a template for the following class:
class SimpleStack
{
public:
SimpleStack();
SimpleStack& push(int value);
int pop();
private:
static const int MAX_SIZE = 100;
int items[MAX_SIZE];
int top;
};
SimpleStack::SimpleStack() : top(-1)
{}
SimpleStack& SimpleStack::push(int value)
{
items[++top] = value;
return *this;
}
int SimpleStack::pop()
{
return items[top--];
}
Everything seems to work except SimpleStack& push(int value):
template <class T>
class SimpleStack
{
public:
SimpleStack();
SimpleStack& push(T value);
T pop();
private:
static const int MAX_SIZE = 100;
T items[MAX_SIZE];
int top;
};
template <class T>
SimpleStack<T>::SimpleStack() : top(-1)
{}
template <class T>
SimpleStack& SimpleStack<T>::push(T value)
{
items[++top] = value;
return *this;
}
template <class T>
T SimpleStack<T>::pop()
{
return items[top--];
}
I keep getting the following errors on the definition of SimpleStack& push(int value): "use of class template requires template argument list," and "unable to match function definition to an existing declaration."
Here is main if it helps:
#include <iostream>
#include <iomanip>
#include <string>
#include "SimpleStack.h"
using namespace std;
int main()
{
const int NUM_STACK_VALUES = 5;
SimpleStack<int> intStack;
SimpleStack<string> strStack;
SimpleStack<char> charStack;
// Store different data values
for (int i = 0; i < NUM_STACK_VALUES; ++i)
{
intStack.push(i);
charStack.push((char)(i + 65));
}
strStack.push("a").push("b").push("c").push("d").push("e");
// Display all values
for (int i = 0; i < NUM_STACK_VALUES; i++)
cout << setw(3) << intStack.pop();
cout << endl;
for (int i = 0; i < NUM_STACK_VALUES; i++)
cout << setw(3) << charStack.pop();
cout << endl;
for (int i = 0; i < NUM_STACK_VALUES; i++)
cout << setw(3) << strStack.pop();
cout << endl;
return 0;
}
Sorry for the excessive code pasting!
Make it
template <class T>
SimpleStack<T>& SimpleStack<T>::push(T value) {...}
When I call merge_sort I get a string of errors as such the most readable is:
no matching function call to dynamic_array<int>::dynamic_array()
Does having a base class instantiate a sub class cause that sub-class to re-instantiate the calling base class?
This was my first guess.
// Calling main function
#include "c_dynamic_array.cpp"
int main()
{
dynamic_array<int> d1(20);
d1.order();cout << d1 << endl;
d1.rorder();cout << d1 << endl;
d1.randorder();cout << d1 << endl;
d1.merge_sort();cout << d1 << endl; // This line starts a string of errors
}
// Dynamic Array Class and Merge Inner (merge sort) Class
#include "c_include.cpp"
/*
Dynamic Array
*/
using namespace std;
template <typename> class merge_inner;
template <class T> class dynamic_array
{
protected:
T* array;
public:
int size;
void rorder();
void order();
void randorder();
void print_operator(ostream&)const;
dynamic_array(int sizein)
{
size=sizein;
array=new T[size]();
}
void merge_sort()
{
merge_inner<T> M1;
}
};
template <class T> void dynamic_array<T>::print_operator(ostream &os=cout)const
{
for (int i = 0; i < size; i++) os << array[i] << endl;
}
template <class T> void dynamic_array<T>::randorder()
{
srand(time(NULL));
int *ap;
for(ap=array;ap!=array+size;++ap){*ap=rand()%size;}
}
template <class T> void dynamic_array<T>::order()
{
int *ap,i=0;
for(ap=array;ap!=array+size;++ap)
{
*ap=i;
++i;
}
}
template <class T> void dynamic_array<T>::rorder()
{
int *ap,i=size-1;
for(ap=array;ap!=array+size;++ap)
{
*ap=i;
--i;
}
}
template<class T> ostream& operator<<(ostream& stream, dynamic_array<T> const& data)
{
data.print_operator(stream);
return stream;
}
/*
Merge Sort
*/
template <class T> class merge_inner : public dynamic_array <T>
{
using dynamic_array<T>::array;
private:
const static int size;
T *scratch;
void flip_if_unordered(int &x, int &y)
{
if(array[x]>array[y])
{
int tmp=array[x];
array[x]=array[y];
array[y]=tmp;
}
}
void merge_algo(int &left, int &right_begin, int &right)
{
int iter,iter_left=left,iter_right=right_begin;
for(iter=left;iter<=right;++iter)
{
if( (iter_right>right) || ((iter_left < right_begin) && (array[iter_left]<=array[iter_right])))
{
scratch[iter]=array[iter_left];
++iter_left;
}
else
{
scratch[iter]=array[iter_right];
++iter_right;
}
}
for(iter=left;iter<=right;++iter){array[iter]=scratch[iter];}
}
void merge_recurse(int left,int right)
{
int left_end=(left+((right-left)/2));
int right_begin=left_end+1;
if(((left+1)==right)){flip_if_unordered(left,right);return;}
else if ((left==right)){return;}
else
{
merge_recurse(left,left_end);
merge_recurse(right_begin,right);
merge_algo(left,right_begin,right);
}
}
public:
merge_inner()
{
scratch = new T[size]();
if(scratch != NULL){merge_recurse(0, size);}
}
};
/*Quick Sort
void quick_sort()
{
quick_recurse(0,size);
}
void quick_recurse(int left, int right)
{
int l = left, r = right, tmp;
int pivot = array[(left + right) / 2];
while (l <= r)
{
while (array[l] < pivot)l++;
while (array[r] > pivot)r--;
if (l <= r)
{
tmp = array[l];
array[l] = array[r];
array[r] = tmp;
l++;
r--;
}
}
if (left < r)quick_recurse(left, r);
if (l < right)quick_recurse(l, right);
}
*/
dynamic_array seems to be missing a default constructor, and since it has a custom constructor the compiler will not provide one. Add this to your class:
dynamic_array()
{
size = 0;
array = new T[0](); // or NULL, but note that new T[0] will be != NULL
}
Alternatively, provide a default sizein for your existing constructor so that it can be used as a default constructor as well:
dynamic_array(int sizein = 0)
Since your base class dynamic_array<T> doesn't have a default constructor, every derived class constructor must call some base constructor one way or another. Put the base initialization in the constructor initializer list. For example:
template <typename T>
class merge_inner : public dynamic_array<T>
{
public:
merge_inner() : dynamic_array<T>(0) { }
// ...
};