Blublublub
Blublublub

Reputation: 57

C++ - undefined reference to Base class operator

I have a template base class Vect, from which VectDynamic is derived.

Base class (Vect.h):

template <typename Elem>
class Vect
{
public:
    virtual Elem& operator[](std::ptrdiff_t);
};

Derived class (VectDynamic.h):

#include "Vect.h"

template <typename Elem>
class VectDynamic: public Vect<Elem>
{
    std::size_t _dim;
    Elem* _val;
public:
    explicit VectDynamic(std::size_t dim = 0): _dim(dim), _val(new Elem[dim]) {}
    VectDynamic(std::size_t, const Elem&);
    VectDynamic(const VectDynamic&); 
    Elem& operator[](std::ptrdiff_t) override;
};

template <typename Elem>
VectDynamic<Elem>::VectDynamic(std::size_t size, const Elem& e):
    _dim(size), _val(new Elem[size]) 
{
    for (std::size_t i = 0; i < size; ++i) _val[i] = e;
}

template <typename Elem>
VectDynamic<Elem>::VectDynamic(const VectDynamic& v): 
    _dim(v._dim), _val(new Elem[v._dim])
{
    for (std::size_t i = 0; i < v._dim; ++i) _val[i] = v._val[i];
}

template <typename Elem>
Elem& VectDynamic<Elem>::operator[] (std::ptrdiff_t i) 
{
    if (std::size_t(i) >= _dim)
        throw std::out_of_range("VectDynamic : Index out of range");
    return _val[i];
}

When I try to create an instance of the derived class like this (main.cpp):

#include "VectDynamic.h"

int main()
{
    VectDynamic<double> v1(5, 2);

    return 0;
}

I end up having this error from both classes:
undefined reference to 'VectDynamic<double>::operator[](long)'

Now I know many posts talk about this kind of error, but after hours of searching I couldn't find any reason why it would happen in my case.
I don't think the error would come from the way I includes the files, as it doesn't work either when everything is in a single file.

I've read in this post that it might be due to the the implicit instantiation of the base class that goes on when the derived class is declared since the base class's methods aren't defined yet.

Do you think that is the problem ? What would be a decent workaround ?

EDIT: Forgot to add the operator[] from the child, added it now (it wasn't causing any error as it was in my code).

Upvotes: 2

Views: 515

Answers (2)

JSF
JSF

Reputation: 5321

Even though Vect<double>::operator[] will never get called, the base vtable must be used for a moment during construction of the derived object and as you declared things, the base vtable has a pointer to that undefined method. That should be solved by adding "=0" (commonly described as "pure virtual") to the declaration of the base method.

Change to

template <typename Elem>
class Vect
{
public:
    virtual Elem& operator[](std::ptrdiff_t)=0;
};

Upvotes: 1

Mark B
Mark B

Reputation: 96291

From the error it seems pretty clear that you just didn't define VectDynamic<double>::operator[]. If you don't want the [] operator just remove the function declarations. If you do want it, you'll need to implement it.

Note that since it's a template class you can't implement the operator in a non-header source file.

And now that I've said all that, let me just also point out since you don't (correctly) follow the rule of 0, 3, or 5 you'll be leaking memory; is there a reason you aren't using std::vector?

Upvotes: 1

Related Questions