This question already has answers here:
Why can templates only be implemented in the header file?
(17 answers)
Closed 4 months ago.
I'm trying to do a custom dynamic array class using templates, and currently the .h file looks like this:
//
// Created by juanfra on 10/10/22.
//
#ifndef IMAGENES_VDINAMICO_H
#define IMAGENES_VDINAMICO_H
#include <cmath>
#include <climits>
using namespace std;
template <typename T>
class VDinamico {
private:
int tamL, tamF;
T *contenedor;
public:
// CONSTRUCTORES
VDinamico<T>();
VDinamico<T>(int tamLog);
VDinamico<T>(const VDinamico<T> &origen);
VDinamico<T>(const VDinamico<T> &origen, unsigned int posicionInicial, unsigned int numElementos);
// OPERADORES
VDinamico &operator=(const VDinamico<T> &vector);
T operator[](int i);
// FUNCIONES
void insertar(const T &dato, unsigned int pos = UINT_MAX);
T borrar (unsigned int pos = UINT_MAX);
bool isGreater(const T& i, const T& j);
void ordenar();
void ordenarRev();
// GETTERS Y SETTERS
int getTamL() const;
void setTamL(int tamL);
int getTamF() const;
void setTamF(int tamF);
T *getContenedor() const;
void setContenedor(T *contenedor);
};
#endif //IMAGENES_VDINAMICO_H
While the .cpp file looks like this:
//
// Created by juanfra on 10/10/22.
//
#include "VDinamico.h"
template<class T>
VDinamico<T>::VDinamico() {
tamF = tamL = 0;
contenedor = new T[tamF];
}
template<class T>
VDinamico<T>::VDinamico(int tamLog) {
tamL = tamLog;
tamF = pow(tamL, 2.0);
contenedor = new T[tamF];
}
template<class T>
VDinamico<T>::VDinamico(const VDinamico<T> &origen) {
tamL = origen.tamL;
tamF = origen.tamF;
contenedor = new T[tamF];
for (int i = 0; i < tamL; i++) {
contenedor[i] = origen.contenedor[i];
}
}
template<class T>
VDinamico<T>::VDinamico(const VDinamico<T> &origen, unsigned int posicionInicial, unsigned int numElementos) {
tamL = numElementos;
tamF = pow(tamL, 2.0);
contenedor = new T[tamF];
for (int i = 0; i < numElementos; i++) {
contenedor[i] = origen.contenedor[i + posicionInicial];
}
}
// OPERADORES
template<class T>
VDinamico<T> &VDinamico<T>::operator=(const VDinamico<T> &vector) {
tamL = vector.tamL;
tamF = vector.tamF;
contenedor = new T[tamF];
T *contenedorAux = vector.contenedor;
for (int i = 0; i < tamL; i++) {
contenedor[i] = contenedorAux[i];
}
}
template<class T>
T VDinamico<T>::operator[](int i) {
return contenedor[i];
}
// FUNCIONES
template<class T>
void VDinamico<T>::insertar(const T &dato, unsigned int pos) {
tamF = this->getTamF();
tamL = this->getTamL();
if (tamF == tamL) { //< Si los tamanyos son iguales, duplico tamF e inserto
T *vAux = new T[tamF * 2];
for (int i = 0; i < tamL; i++) {
vAux[i] = contenedor[i];
}
delete[]contenedor;
contenedor = vAux;
}
if (pos == UINT_MAX) { //< Si la posición no se indica, insertamos por el final
contenedor[tamL++] = dato;
} else { //< Si la posición se indica, abrimos un hueco en la posición indicada copiando el resto del vector
for (int i = tamL - 1; i >= pos; i--) {
contenedor[i + 1] = contenedor[i];
}
}
this->setTamL(tamL + 1);
}
template<class T>
T VDinamico<T>::borrar(unsigned int pos) {
tamF = this->getTamF();
tamL = this->getTamL();
if (tamL*3 < tamF){ //< Si tamL es 3 veces menor que tamF, hago un nuevo vector de tamF/2
T *vAux = new T[tamF/2];
for (int i = 0; i < tamL; i++){
vAux[i] = contenedor[i];
}
delete[]contenedor;
contenedor = vAux;
}
if (pos == UINT_MAX){
return contenedor[tamL--];
} else {
for (int i = pos; i < tamL; i++){
contenedor[i] = contenedor[i+1];
}
}
this->setTamL(tamL--);
return contenedor;
}
template<class T>
bool VDinamico<T>::isGreater(const T& i, const T& j) {
return (i.getId() > j.getId());
}
template<class T>
void VDinamico<T>::ordenar() {
sort(contenedor, contenedor + tamL);
}
template<class T>
void VDinamico<T>::ordenarRev() {
sort(contenedor, contenedor + tamL, isGreater());
}
// GETTERS Y SETTERS
template<class T>
int VDinamico<T>::getTamL() const {
return tamL;
}
template<class T>
void VDinamico<T>::setTamL(int tamL) {
VDinamico::tamL = tamL;
}
template<class T>
int VDinamico<T>::getTamF() const {
return tamF;
}
template<class T>
void VDinamico<T>::setTamF(int tamF) {
VDinamico::tamF = tamF;
}
template<class T>
T *VDinamico<T>::getContenedor() const {
return contenedor;
}
template<class T>
void VDinamico<T>::setContenedor(T *contenedor) {
VDinamico::contenedor = contenedor;
}
My problem is that, in the .h, everytime I use <T>, it throws me an error like:
error: expected unqualified-id before ‘)’ token in line 20
error: expected unqualified-id before ‘int’ in line 22
error: expected unqualified-id before ‘const’ in line 24
and so on...
What am I doing wrong?
I removed all the <T> in the .h file, to not split a template class across .h and .cpp files.
Here is why: Why can templates only be implemented in the header file?
Related
Ok i wrote this class that counts how many leaves are there in a binary tree:
#ifndef _UTIL_BIN_TREE_H_
#define _UTIL_BIN_TREE_H_
#include"bin_treec.h"
template <class T>
class util_bin_tree
{
public:
static int n_leaf(const Bin_treec<T>& T) {
int i;
if (!T.empty())
{
if (T->spazio[i].sinistro == NULL && T->spazio[i].destro == NULL)
return 1;
else
return n_leaf(T->T->spazio[i + i].sinistro) + n_leaf(T->T->spazio[i + i].destro);
}
};
static int n_level(const Bin_treec<T>& T, int i)
{
//
};
};
#endif
this is the class that creates the binary tree:
#ifndef _Bin_treecC_H_
#define _Bin_treecC_H_
#include "Bin_tree.h"
#include "exceptions.h"
template <class T>
class Bin_treec : public Bin_tree<T, int> {
static const int NIL = -1;
public:
typedef typename Bin_tree<T, int>::value_type value_type;
typedef typename Bin_tree<T, int>::Nodo Nodo;
struct _cella {
Nodo genitore;
Nodo sinistro;
Nodo destro;
value_type valore;
};
typedef struct _cella Cella;
// costruttori e distruttori
Bin_treec();
Bin_treec(int);
~Bin_treec();
// operatori
void create();
bool empty() const;
Nodo root() const;
Nodo parent(Nodo) const;
Nodo sx(Nodo) const;
Nodo dx(Nodo) const;
bool sx_empty(Nodo) const;
bool dx_empty(Nodo) const;
//void costr(Bin_treec<T>);
void erase(Nodo);
T read(Nodo) const;
void write(Nodo, value_type);
void ins_root();
void ins_sx(Nodo);
void ins_dx(Nodo);
private:
int MAXLUNG;
Cella* spazio;
int nNodi;
Nodo inizio;
Nodo libera;
};
template <class T>
Bin_treec<T>::Bin_treec()
{
MAXLUNG = 100;
spazio = new Cella[MAXLUNG];
create();
}
template <class T>
Bin_treec<T>::Bin_treec(int nNodi) : MAXLUNG(nNodi)
{
spazio = new Cella[nNodi];
create();
}
template <class T>
Bin_treec<T>::~Bin_treec()
{
erase(inizio);
delete[] spazio;
}
template <class T>
void Bin_treec<T>::create()
{
inizio = NIL;
for (int i = 0; i < MAXLUNG; i++)
{
spazio[i].sinistro = (i + 1) % MAXLUNG;
}
libera = 0;
nNodi = 0;
}
template <class T>
bool Bin_treec<T>::empty() const
{
return(nNodi == 0);
}
template <class T>
typename Bin_treec<T>::Nodo Bin_treec<T>::root() const
{
return(inizio);
}
template <class T>
typename Bin_treec<T>::Nodo Bin_treec<T>::parent(Nodo n) const
{
if (n != inizio)
return (spazio[n].genitore);
else
return(n);
}
template <class T>
typename Bin_treec<T>::Nodo Bin_treec<T>::sx(Nodo n) const
{
if (!sx_empty(n))
return (spazio[n].sinistro);
else
return(n);
};
template <class T>
typename Bin_treec<T>::Nodo Bin_treec<T>::dx(Nodo n) const
{
if (!dx_empty(n))
return (spazio[n].destro);
else
return(n);
}
template <class T>
bool Bin_treec<T>::sx_empty(Bin_treec<T>::Nodo n) const
{
return (spazio[n].sinistro == NIL);
}
template <class T>
bool Bin_treec<T>::dx_empty(Bin_treec<T>::Nodo n) const
{
return (spazio[n].destro == NIL);
}
template <class T>
void Bin_treec<T>::ins_root()
{
if (inizio == NIL)
{
inizio = libera;
libera = spazio[libera].sinistro;
spazio[inizio].sinistro = NIL;
spazio[inizio].destro = NIL;
nNodi++;
}
else
throw RootExists();
}
template <class T>
void Bin_treec<T>::ins_sx(Nodo n)
{
if (inizio == NIL)
throw EmptyTree();
if (n == NIL)
throw NullNode();
if (spazio[n].sinistro != NIL)
throw NodeExists();
if (nNodi >= MAXLUNG)
throw FullSize();
else
{
Nodo q = libera;
libera = spazio[libera].sinistro;
spazio[n].sinistro = q;
spazio[q].sinistro = NIL;
spazio[q].genitore = n;
spazio[q].destro = NIL;
nNodi++;
}
}
template <class T>
void Bin_treec<T>::ins_dx(Nodo n)
{
if (inizio == NIL)
throw EmptyTree();
if (n == NIL)
throw NullNode();
if (spazio[n].destro != NIL)
throw NodeExists();
if (nNodi >= MAXLUNG)
throw FullSize();
else
{
Nodo q = libera;
libera = spazio[libera].sinistro;
spazio[n].destro = q;
spazio[q].genitore = n;
spazio[q].sinistro = NIL;
spazio[q].destro = NIL;
nNodi++;
}
}
template <class T>
void Bin_treec<T>::erase(Nodo n)
{
if (n != NIL) {
if (!sx_empty(n))
erase(spazio[n].sinistro);
if (!dx_empty(n))
erase(spazio[n].destro);
if (n != inizio) {
Nodo p = parent(n);
if (spazio[p].sinistro == n)
spazio[p].sinistro = NIL;
else
spazio[p].destro = NIL;
}
else
inizio = NIL;
nNodi--;
spazio[n].sinistro = libera;
libera = n;
}
else
throw NullNode();
}
template <class T>
T Bin_treec<T>::read(Nodo n) const
{
if (n != NIL)
return (spazio[n].valore);
else
throw NullNode();
}
template <class T>
void Bin_treec<T>::write(Nodo n, value_type a)
{
if (n != NIL)
spazio[n].valore = a;
else
throw NullNode();
}
#endif /* _Bin_treecC_H_ */
this is the main
#include "util_bin_tree.h"
#include <iostream>
using namespace std;
int main() {
Bin_treec<int> T;
typename Bin_treec<int>::Nodo n1 = 0, n2 = 0;
T.ins_root();
T.write(T.root(), 1);
n1 = T.root();
T.ins_sx(n1);
T.ins_dx(n1);
T.write(T.sx(n1), 2);
n1 = T.dx(n1);
T.write(n1, 3);
T.ins_dx(n1);
T.write(T.dx(n1), 4);
T.print();
cout << T;
n_leaf(T); // here i have error C3681
It says that my function is undeclared but i don't know why.
Full error is :
Severity Code Description Project File Line Suppression State
Error C3861 'n_leaf': identifier not found esercizio C:\Users\mypc\source\repos\esercizio\test.cpp 26
I also have a virtual bin_tree header where util_bin_tree is not specified, but I don't think it really matters because i don't use any functions related to the tree.
Also, is it my way to pass an array from T correct? I just wanted to pass an entire object to another class function and the compiler doesn't find any error for the time being. But i can't test the function just because of that problem. Any help?
Your n_leaf function is not a namespace-scoped function, it's a static function inside the util_bin_tree class. You can call it with util_bin_tree<int>::n_leaf(T).
Since your util_bin_tree class does not have any data members, you could use namespace util_bin_tree { } instead, and put template<class T> before each function.
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.
this is where i define my template and 3 additional classes
#ifndef PLANILHAH
#define PLANILHAH
#include <iostream>
#include "planilha_func.h"
template <class TIPO> class planilha {
friend class celula;
friend class listaT;
friend class elo;
protected:
celula * primeiro;
unsigned int count;
public:
planilha();
planilha(const planilha<TIPO>& origem);
~planilha(void)
TIPO obtem_valor(const unsigned int num_cel);
//many more methods
};
i dont know if I should make this a nested class in 'planilha' or not if i make it nested, how do i implement it? it needs to recieve the type 'TIPO'
template <class TIPO> class celula{
friend class listaT;
friend class elo;
protected:
unsigned int idCelula;
TIPO constante;
TIPO total;
listaT termos;
//etc
void insere(int novoCons);
void apaga();
void setIdCelula(unsigned int idCelula);
void setTotal(TIPO total);
TIPO getTotal() const;
TIPO getConstante() const;
void setConstante(TIPO constante);
};
I dont know if friend class is the best option, these are used in the class celula
class listaT {
friend class elo;
protected:
elo * primeiro;
public:
listaT();
~listaT();
listaT(listaT& origem);
};
class elo {
friend class listaT;
protected:
elo();
elo(unsigned int novaRef, double novoFator, bool x = true, elo * proxElo = NULL);
elo operator=(const elo& origem);
};
#endif;
heres where i implement them, i am getting 100 errors or more. i cant understand why
#include "planilha.h"
#include <iostream>
#include <cstdlib>
#include <fstream>
using namespace std;
template <class TIPO>
planilha<TIPO>::planilha() {
primeiro = NULL;
count = 1;
}
template <class TIPO>
planilha<TIPO>::~planilha(void) {
celula * p = primeiro;
while(primeiro!=NULL) {
p=primeiro->prox;
delete primeiro
primeiro=p;
}
}
template <class TIPO>
planilha<TIPO>::planilha(const planilha<TIPO>& origem) {
this->count = origem.count;
celula * p1;
this->primeiro = NULL;
celula * p2;
for(p2 = origem.primeiro; p2!=NULL; p2=p2->prox) {
p1 = p2;
if(this->primeiro == NULL) {
this->primeiro = p1;
}
p1 = p1->prox;
}
}
template <class TIPO>
unsigned int planilha<TIPO>::getCount() const {
return count;
}
template <class TIPO>
void typename planilha<TIPO>::setCount(unsigned int count) {
this->count = count;
}
template <class TIPO>
celula * planilha<TIPO>::finder(unsigned int id) {
celula * resposta;
for(resposta=this->primeiro; resposta!=NULL; resposta=resposta->prox) {
if(resposta->idCelula == id) break;
}
return resposta;
}
template <class TIPO>
celula<TIPO>::celula() {
prox = NULL;
}
template <class TIPO>
celula<TIPO>::celula(unsigned int novoId, TIPO novaConstante, planilha<TIPO> * proxCel) {
idCelula = novoId;
constante = novaConstante;
total = novaConstante;
prox = proxCel;
}
template <class TIPO>
void celula<TIPO>::setTotal(TIPO total) {
this->total = total;
}
listaT::listaT() {
this->primeiro = NULL;
}
listaT::~listaT() {
elo * p = primeiro;
while(primeiro!=NULL) {
p=primeiro->prox;
delete primeiro;
primeiro=p;
}
}
listaT::listaT(listaT& origem) {
elo * p2;
elo * p1;
primeiro = NULL;
for(p2 = origem.primeiro; p2!=NULL; p2 = p2->prox) {
p1 = p2;
if(primeiro == NULL) {
primeiro = p1;
}
p1 = p1->prox;
}
}
bool listaT::vazia() {
return (primeiro == NULL);
}
void listaT::insere(int novaRef, double novoFator, bool absoluta) {
elo * p = primeiro;
elo * novoElo = new elo(novaRef, novoFator, absoluta);
if(vazia()) {
primeiro = novoElo;
} else {
while(p->prox!=NULL) {
p = p->prox;
}
p->prox = novoElo;
}
}
bool listaT::operator==(const listaT &listaT2) {
elo * p1 = this->primeiro;
elo * p2 = listaT2.primeiro;
bool resposta = true;
while(p1!=NULL && p2!=NULL) {
if(p1->fator != p2->fator || p1->referencia != p2->referencia || p1->absolut != p2->absolut) {
resposta = false;
}
p1=p1->prox;
p2=p2->prox;
}
if(p2!=NULL || p1!=NULL) {
resposta = false;
}
return resposta;
}
elo * listaT::getPrimeiro() {
elo * resposta;
resposta = primeiro;
return resposta;
}
elo::elo() {
prox = NULL;
}
elo::elo(unsigned int novaRef, double novoFator, bool x, elo * proxElo) {
referencia = novaRef;
fator = novoFator;
prox = proxElo;
absolut = x;
}
elo elo::operator=(const elo& origem) {
unsigned int r = origem->referencia;
double f = origem.fator;
bool x = origem.absolut;
elo p(r, f, x);
return p;
}
Have you got an include for the cpp files, and have you made sure that if you dont you need to put template class source code in the same file as the header
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) { }
// ...
};