3

Upon request I have post the rest of the code in idone.com

So I have to create my own Vector Class and I did. It is required. When I implement it in another class however, It gives me these errors This is how I am trying to implement it:

#include "Vector.h"

class UserDB
{
private:
    Vector<AccountInfo*> _accounts;
//more code that previous to this implementation worked fine.
};

I was hoping someone could tell me what to do about it. I'm completely clueless in this one. Java never gave such errors, whatsoever... EDIT: I have also realized that when I say something like Vector<int> _accounts; it runs completely fine, however when done with a class such as Vector, it seems almost impossible to fix it. I am reading a lot, but I still cannot seem to find a fix to this.

This is my Vector Header

#include "ArrayClass.h" //Class with more methods
#include "AbstractVector.h" //Another class with more method
template <class DT>
class Vector: virtual public ArrayClass<DT>,
virtual public AbstractVector<DT>
{
protected:
int _currSize;
int _incFactor;
public:
Vector ();
Vector (int n);
Vector (int n, DT& val);
Vector (const Vector<DT>& v);
Vector (const ArrayClass<DT>& ac);
virtual ~Vector();
void operator= (const Vector<DT>& v);
void operator= (const ArrayClass<DT>& ac);
virtual void insert (const DT& item, int index);
virtual void remove (int index);
virtual void add (const DT& item);
virtual int size() const;
virtual int capacity() const;
virtual int incFactor() const;
virtual void setIncFactor(int f);
void setCapacity(int c);
};

And this one is the Actual code Vector.cpp

#include "Vector.h"

template <class DT>
Vector<DT>::Vector () : ArrayClass<DT>()
{
    _currSize = 0;
    _incFactor = 5;
}
Vector<DT>::~Vector ()
{
_currSize = NULL;
_incFactor = NULL;
}
template <class DT>
Vector<DT>::Vector (int n): ArrayClass<DT>(n)
{
    _currSize = 0;
    _incFactor = (n+1)/2;
}
template <class DT>
Vector<DT>::Vector (int n, DT& val)
    : ArrayClass<DT>(n, val)
{
    _currSize = 0;
    _incFactor = n/2;
}
template <class DT>
Vector<DT>::Vector (const Vector<DT>&v)
    : ArrayClass<DT> (v)
{
    _currSize = v._currSize;
    _incFactor = v.incFactor();
}
template <class DT>
Vector<DT>::Vector (const ArrayClass<DT>& ac)
    : ArrayClass<DT> (ac)
{
    _currSize = ac.size();
    _incFactor = (_currSize+1)/2;
}
template <class DT>
void Vector<DT>::operator= (const Vector<DT>& v)
{
    ArrayClass<DT>::copy (v);
    _currSize = v._currSize;
    _incFactor = v.incFactor();
}
//template <class DT>
//void Vector<DT>::operator= (const ArrayClass<DT>&ac)
//{
//  ArrayClass<DT>::copy (ac);
//  _currSize = ac.size();
//  _incFactor = (_currSize+1)/2;
//}
template <class DT>
int Vector<DT>::size() const
{
    return _currSize;
}
template <class DT>
int Vector<DT>::capacity() const
{
    return _size;
}
template <class DT>
int Vector<DT>::incFactor() const
{
    return _incFactor;
}
template <class DT>
void Vector<DT>::add (const DT& item)
{
    insert (item, _currSize);
}
template <class DT>
void Vector<DT>::setIncFactor(int f)
{
    if (f >= 0) _incFactor = f;
}
template <class DT>
void Vector<DT>::setCapacity(int c)
{
    int len = _currSize;
    if (len > c) len = c;
    DT* paNew = new DT[c];
    if (paNew == NULL)
    {
        throw ArrayMemoryException();
    }
    for (int i = 0; i < len; i++)
    {
        paNew[i] = paObject[i];
    }
    if (paObject != NULL)
    {
        delete[] paObject;
    }
    paObject = paNew;
    _size = c;
    if (_currSize > len)
    {
        _currSize = len;
    }
}
template <class DT>
void Vector<DT>::insert (const DT& item, int index)
{
if ((index < 0) || (index > _currSize))
{
throw ArrayBoundsException();
}
if (_currSize+1 == _size)
{
setCapacity (_size + _incFactor);
}
_currSize++;
for (int i = _currSize-1; i > index; i--)
{
(*this)[i] = (*this)[i-1];
}
(*this)[index] = item;
}
template <class DT>
void Vector<DT>::remove (int index)
{
if ((index < 0) || (index >= _currSize))
{
throw ArrayBoundsException();
}
if (_currSize <= _size-_incFactor)
{
setCapacity (_size - _incFactor);
}
for (int i = index; i < _currSize-1; i++)
{
(*this)[i] = (*this)[i+1];
}
_currSize--;
}
Ren
  • 4,594
  • 9
  • 33
  • 61
  • 4
    let me guess, you put the definition of your vectors member functions in a .cxx file? – PlasmaHH Feb 18 '12 at 22:38
  • What do you have in `Vector.h`? – Matteo Italia Feb 18 '12 at 22:39
  • Is your Vector class marked public? It in the same project or a separate project? – D Stanley Feb 18 '12 at 22:39
  • Nope. Vector.h for headers and Vector.cpp for the actual code in it. – Ren Feb 18 '12 at 22:39
  • 1
    Post your Vector.h and Vector.cpp files, or at least the first 20-30 lines of each. – rob mayoff Feb 18 '12 at 22:39
  • 1
    @PlasmaHH: more looks like the cpp is not included in the linkage... – Alexander Pavlov Feb 18 '12 at 22:41
  • @DStanley Uh... I will try to make it public and see how it goes, although I was never encouraged to make classes public or private in C++ – Ren Feb 18 '12 at 22:41
  • Is it me or do the errors have nothing to do with this source? I mean, the errors are about class `AccountInfo`... – Mr Lister Feb 18 '12 at 22:44
  • @MrLister : the OP explained it: "When I implement it **in another class** however, It gives me these errors" – qdii Feb 18 '12 at 22:54
  • possible duplicate of [Include .cpp file?](http://stackoverflow.com/questions/8836871/include-cpp-file) – Mooing Duck Feb 18 '12 at 22:55
  • @MooingDuck Saw it, but I thought it would be a good idea to post mine anyway since the problem and solution to that post were different than what I could apply to mine – Ren Feb 18 '12 at 23:01
  • 1
    At the point, where template is being instantiated, template definition should be in scope. Because compiler uses that definition to generate a new class ( with given template argument). So, this implies, the template should be defined in a header file. – Aman Aggarwal Feb 18 '12 at 23:06
  • @Yokhen: Check again, the first answer to that question is _exactly_ how to solve your issue (as are, I expect, all the other answers). – Mooing Duck Feb 18 '12 at 23:09
  • @fizzbuzz If you can see (or maybe I am getting blind) the template `template
    ` is declared everytime; for the class as well as for the methods....
    – Ren Feb 18 '12 at 23:27
  • @AlexanderPavlov: Its a template, you can not have the definition of its functions in a seperate TU and just link that, it has to be available at instantiation time. – PlasmaHH Feb 19 '12 at 11:34
  • @PlasmaHH: good point, more about it for the curious [here](http://www.parashift.com/c++-faq-lite/templates.html#faq-35.12). – Alexander Pavlov Feb 19 '12 at 12:03
  • @PlasmaHH are you saying I should put everything in a .cpp file (Vector.cpp)? And if that is the case, how can I `#include` it? C++ will only let me to include headers (i.e. `#include "Vector.h"`). How can I work it out? I'm getting desperate. – Ren Feb 19 '12 at 18:48
  • @AlexanderPavlov I just started reading this, I hope this can fix my problem. It looks very similar to what I am experiencing. Will be reporting back when I'm done trying to fix it. – Ren Feb 19 '12 at 19:19
  • If this conversation needs to be continued, please take it to a chat-room. Thanks! – Lasse V. Karlsen Feb 19 '12 at 19:49
  • @Yokhen: no, you should put everythign in the .h file. – PlasmaHH Feb 20 '12 at 13:49

2 Answers2

4

While compiling your code, at the point, where template is being instantiated, i.e. in your code

Vector<AccountInfo*> _accounts;

the compiler will generate a new class using template Vector ( with given template argument i.e AccountInfo*). Thus compiler needs access to implementation of template Vector<T> at this point.

So, this implies, the template Vector<T> should be completely implemented in a header file.

If you do want to keep the separation between template definition and implementation then
you can have two header files, one Vector.h and other Vector_impl.h, with Vector_impl.h containing the implementation of the template.

Include Vector.h in the Vector_impl.h and Include Vector_impl.h in the .cpp file where you are instantiating the template i.e. Vector < AccountInfo*>.

Aman Aggarwal
  • 3,905
  • 4
  • 26
  • 38
  • I am a little confused. What about the "template `Vector`" exactly should I "implement" to fix the problem? Do you mean to put the contents of Vector.cpp in Vector.h? – Ren Feb 18 '12 at 23:35
  • @Yokhen, you should understand, a template is only used to generate other classes. If a template is not used i.e not instantiated at any place in your code, then no code is generated for that template. Therefore, a template implementation should be "#included" in the file where you are instantiating it. – Aman Aggarwal Feb 18 '12 at 23:40
  • So, just removed the Vector.cpp file and added its contents to Vector.h and I'm getting the same errors [with different content...](http://i.imgur.com/o6IbB.png) – Ren Feb 18 '12 at 23:50
  • @Yokhen : are you sure the constructor for ArrayClass is defined too? – qdii Feb 19 '12 at 09:42
  • @Yokhen If possible post ArrayClass.h and Abstractvector.h or any other files , we might need to compile your code. You can use http://codepad.org/ or http://pastebin.com/ or http://ideone.com/ – Aman Aggarwal Feb 19 '12 at 12:41
  • @victor yes I did sir. I will fix it now in the question. – Ren Feb 19 '12 at 18:21
  • @fizzbuzz Just updated it on that. Normally if I posted all of it, everyone would be mad and would get downvoted, so that's why I didn't upload it everything at once. – Ren Feb 19 '12 at 18:24
  • @Yokhen your uploaded code compiles after some rearrangement and some minor modifications and most importantly after defining the destructor for ArrayClass. Check it out here http://ideone.com/ngViq – Aman Aggarwal Feb 20 '12 at 04:04
  • Man, thank you very much! That was very helpful :D Now I get it! – Ren Feb 20 '12 at 04:52
2

these errors are here because the link phase (which takes place after the compile phase) couldn’t find the binary code for the constructor and destructor of Vector and the destructor of ArrayClass.

My guess is that you forgot to define those function in the template class, but you declared them. It compiled before because you did not actually instantiate an object of that class (my guess). The easy solution (assuming my guess is correct) is to put the method definitions in the same file as the declarations (i.e. Vector.h). Could you show what’s in "Vector.h"?

Last remark: the "private" keyword is useless here, class are private by default.

EDIT: To extend my remark, your code is actually missing a definition for Vector::~Vector. Java did not complain about it because destructors don’t exist there :)

Martin York
  • 257,169
  • 86
  • 333
  • 562
qdii
  • 12,505
  • 10
  • 59
  • 116
  • About your last remark: being explicit is rarely a bad thing. – Armen Tsirunyan Feb 18 '12 at 22:46
  • I’m not entirely satisfied though. I can’t figure the reason why the first error popped. – qdii Feb 18 '12 at 22:53
  • The first error was because the `Vector::Vector(void)` constructor was not instantiated in any translation unit, and thus the symbol could not be linked. It was not instantiated, because no TU had both the template function definition, _and_ the type to instantiate with, because the template function definition was in it's own cpp file. – Mooing Duck Feb 18 '12 at 23:12
  • So I added a Destructor a while ago and the problem persists. – Ren Feb 18 '12 at 23:45