1

I have tried the following hierarchy and it doesn't link. The call to c->Execute() is not seen since it seems to be masked by the Execute in Derived and it doesn't find an adequate type to use. I would have thought that if there was a problem, it would have to show at compilation. I have tried with GCC 4.8 online and with the borland compiler on Windows. The error message is similar in both cases. Something in the order of:

/tmp/ccrT5mNy.o:(.rodata._ZTV7DerivedI5TypeCE[_ZTV7DerivedI5TypeCE]+0x10): undefined reference to `Derived<TypeC>::Execute()'
collect2: error: ld returned 1 exit status

I would be very grateful for any pointers.

#include <iostream>

class BaseType 
{
public: 
    BaseType() {}
    virtual void Execute() { std::cout << "BaseType execute..." << std::endl; };

protected:
};

struct TypeA;
struct TypeB;
struct TypeC;

class Derived2 : public BaseType
{
public:
    Derived2() : BaseType() {}
    virtual void Execute() { std::cout << "Derived execute2" << std::endl; }

protected:
};


template <typename T>
class Derived : public BaseType
{
public:
    Derived() : BaseType() {}
    virtual void Execute();

protected:
};

template <typename T>
class GrandChild : public Derived<T>
{
public:
    GrandChild() : Derived<T>() {}
    void Execute();
};

template<>
void Derived<TypeA>::Execute() { std::cout << "Derived execute... TypeA" << std::endl; }
template<>
void Derived<TypeB>::Execute() { std::cout << "Derived execute... TypeB" << std::endl; }
template<>
void GrandChild<TypeC>::Execute() { std::cout << "Derived execute... TypeC" << std::endl; }


int main()
{
    BaseType* a = new Derived<TypeA>();      
    BaseType* b = new Derived<TypeB>();      
    BaseType* c = new GrandChild<TypeC>();      
    BaseType* d2 = new Derived2();
    a->Execute();
    b->Execute();
    c->Execute();
    d2->Execute();

    delete a;
    delete b;
    delete c;
    delete d2;
}
Martin Serrano
  • 3,727
  • 1
  • 35
  • 48
Some Dude
  • 53
  • 4

1 Answers1

1

Derived<TypeC>::Execute() must be defined even if you never call it, since you're instantiating the class template. Try adding an empty definition, or one that throws, etc. and the program should link and work as you expect.

aschepler
  • 70,891
  • 9
  • 107
  • 161
  • It certainly does work by adding the specialisation that you suggest. Thank you very much for the answer. – Some Dude Dec 09 '14 at 12:18