Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to subclass a templated base class?

I have the following data structures:

struct fastEngine { ... }
struct slowEngine { ... }

template<typename T>
class Car {
   T engine;
   vector<T> backupEngines;

   virtual void drive() = 0;
}

class FastCar : public Car<fastEngine> {
   virtual void drive() {
      // use the values of "engine" in some way
   }
}

class SlowCar : public Car<slowEngine> {
   virtual void drive() {
      // use the values of "engine" in some way
   }
}

Car* getCarFromCarFactory() {  // 1
   if (randomNumber == 0)
      return new FastCar();
   else
      return new SlowCar();
}

void main() {
   Car* myCar = getCarFromCarFactory(); // 2
   myCar->drive();
}

The compiler complains at locations 1 and 2 because it requires that I define Car* with template parameters. I don't care what templated version of Car I'm using, I just want a pointer to a Car that I can drive. The engine structs must be structs because they are from existing code and I don't have control over them.

like image 519
Brian Avatar asked Sep 25 '09 20:09

Brian


People also ask

Can a non templated class have a templated member function?

A non-template class can have template member functions, if required. Notice the syntax. Unlike a member function for a template class, a template member function is just like a free template function but scoped to its containing class.

Can a template base class derived?

Inheriting from a template classIt is possible to inherit from a template class. All the usual rules for inheritance and polymorphism apply. If we want the new, derived class to be generic it should also be a template class; and pass its template parameter along to the base class.

What is base class and subclass?

Definitions: A class that is derived from another class is called a subclass (also a derived class, extended class, or child class). The class from which the subclass is derived is called a superclass (also a base class or a parent class).


2 Answers

You could create a non-templated base class that Car<T> inherits, e.g.

struct ICar {
    virtual void drive() = 0;
};

template <typename T>
class Car : public ICar {
    // ...
}

int main() { // BTW, it's always `int main`, not `void main`
    ICar *myCar = getCarFromCarFactory();
    myCar->drive();
}
like image 179
Cat Plus Plus Avatar answered Oct 22 '22 03:10

Cat Plus Plus


PiotrLegnica's answer is right, but I'd just like to add a few points:

class templates are not classes

In your code, Car is a class template. A class template is not a class, it is only ... a template from which classes can be defined, and different instantiations of a same template do not necessarily lead to types having the same interface. A simple example:

template<class T>
class Foo
{
public:
  T Bar();
  bool Baz(const T&);
};

struct and class is (almost) the same thing

The engine structs must be structs because they are from existing code and I don't have control over them.

I assume that you wrote this because you were suspecting that the problem was related to the use of structs instead of classes as template parameters. This is not the case. In C++, struct and class is almost the same thing. The only difference is that the default access and inheritance are public with a struct while they are private with a class.

like image 30
Éric Malenfant Avatar answered Oct 22 '22 03:10

Éric Malenfant