2

I have a base class which has a virtual function :

class Base {
   ...
   virtual void myFunction() { assert(0 && "not implemented yet"); }

}

and a derived (template) class of Base :

DerviedClass.hpp :

Template<typename T>
class DerivedClass : public Base, public T {

  ...
  void myFunction();

}

DerivedClass.cpp :

template <>
void DerivedClass<ClassA>::myFunction() {
 //Something ClassA is suppose to do
}

This compiles. But when I try to instanciate a DerivedClass<ClassB> I get the error :

IProject.o:-1: erreur : undefined reference to `DerivedClass<ClassB>::myFunction()'

Why do I have this error? Why it does not take Base::myFunction instead of forcing me to implement a generic myFunction in DerivedClass or a specialized function DerivedClass::myFunction?

Note : the assert in myFunction is because ClassB is not supposed to call myFunction during runtime. For exemple if myFunction is getRadius, DerivedClass<Circle>::getRadius() is okay but DerivedClass<Square>::getRadius() should not be called.

Note 2 : The other topics I found were not clear about this point

LogicStuff
  • 19,397
  • 6
  • 54
  • 74
ElevenJune
  • 423
  • 1
  • 4
  • 21
  • You probably want to rethink your design to forbid `DerivedClass::getRadius()`. – Jarod42 Jul 28 '16 at 12:56
  • 1
    `DerivedClass::getRadius()` should not have existed in the first place. – n. m. could be an AI Jul 28 '16 at 12:58
  • I did this design to manipulate all DerivedClass as Base without having to `dynamic_cast` when I want to call a function from a base class. (There is a lot a derived class with a lot a function which need to be call) – ElevenJune Jul 28 '16 at 12:59
  • @n.m. I do not want `DerivedClass::getRadius()` to exist either, that why I want DerivedClass to call the function from Base. – ElevenJune Jul 28 '16 at 13:00
  • 1
    `Base::getRadius()` should bot exist either (if it exists, then it exists for all derived classes too). Implementing all possible derived methods in the base class with `assert(0 && "not implemented")` is a moral equivalent of dynamic_cast everywhere. This is the exact opposite of OOP. – n. m. could be an AI Jul 28 '16 at 13:02

3 Answers3

2

Why it does not take Base::myFunction instead of forcing me to implement a generic myFunction in DerivedClass or a specialized function DerivedClass::myFunction?

You forced that yourself, by the declaration:

void myFunction();

Consider fully specializing the class template, which will generate classes conditionally with or without overriding myFunction, e.g.:

template <typename T>
class DerivedClass : public Base, public T {
    // not overriding    
};

template <>
class DerivedClass<ClassA> : public Base, public ClassA {
    void myFunction() override;
};

template <>
void DerivedClass<ClassA>::myFunction() {
    // something ClassA is supposed to do
}

If there's some common stuff, you can put it in:

template <typename T>
class DerivedClassCommons : public Base, public T {
    // common stuff
};

and then refactor DerivedClass to use single inheritance of this class template.

That's it for your question, but as others were noting, I think you have a bigger, design problem.

LogicStuff
  • 19,397
  • 6
  • 54
  • 74
2

Another method to fix the compiler error (not the design error) is to move the definition of myFunction to the derived template:

class Base {
   virtual void myFunction() = 0;
}

template<typename T>
class DerivedClass : public Base, public T {
   void myFunction() {
      throw "not implemented, go away";
   }
}

and then specialise only the methods you need:

template <>
void DerivedClass<ClassA>::myFunction() {
 //Something ClassA is suppose to do
}
n. m. could be an AI
  • 112,515
  • 14
  • 128
  • 243
1

The function is already declared for all types. Definition might come from anywhere, including other compilation units. You'll only need the definition when the function is referred - and your virtual function is (implicitly) referred during construction.

lorro
  • 10,687
  • 23
  • 36
  • I think that I understand your answer. If I do not make any reference to any DerivedClass, I will never have a compilation problem beacause the code of DerivatedClass will not be generated and will never try to find myFunction. But if I must use a DerivedClass somewhere in the code, is there a way to make call Base::myFunction() ?? – ElevenJune Jul 28 '16 at 13:04
  • @ElevenJune Your derived class redeclares the function it inherits from the base. So, to match that declaration, a definition must be available. If you don't want to override the base's version, then you need to.... not redeclare it in the derived. This is exactly the same as with any other class: the fact that your derived class here happens to be a template is completely incidental. – underscore_d Jul 28 '16 at 13:14