waas1919
waas1919

Reputation: 2605

Template class on a abstract class

So I have a class template Foo:

template <typename T>
class Foo
{
public:
    Foo();
    ~Foo();
   //...
};

I have two derived classes from the Foo class:

class FooDerived1 : public Foo<int>
{
public:
    FooDerived1 ();
    ~FooDerived1 ();
};

class FooDerived2 : public Foo<double>
{
public:
    FooDerived2 ();
    ~FooDerived2 ();
};

But now I saw that the class template was being used on a abstract class IBar like this:

class Foo;

class IBar
{
public:
    virtual void placeFoo(Foo& foo) = 0; //error
    virtual void removeFoo(Foo& foo) = 0;
};

I know I cannot use templates classes in abstract virtual classes.

But..in a case like this, what should I do?

I really need the IBar abstract class like this...

Forget the usage of template classes?

Upvotes: 1

Views: 102

Answers (2)

Mateusz Grzejek
Mateusz Grzejek

Reputation: 12058

If you need common behaviour, create base class for all instances of Foo<>:

class FooBase
{
    //common interface and data
};

template <class T>
class Foo : public FooBase
{
};

And then:

class FooBase;

class IBar
{
public:
    virtual void placeFoo(FooBase& foo) = 0; //ok
    virtual void removeFoo(FooBase& foo) = 0;
};

The thing is, that you try to mix templates (compile time) and dynamic polymorphism (runtime), which can be problematic (is it what you meant by "I know I cannot use templates classes in abstract virtual classes"?).

Why not stick to using templates?

class IBar
{
public:
    template <class T>
    void placeFoo(Foo<T>& foo);

    template <class T>
    void removeFoo(Foo<T>& foo);
};

or:

template <class T>
class IBar
{
public:
    void placeFoo(Foo<T>& foo);
    void removeFoo(Foo<T>& foo);
};

Upvotes: 1

Christian Hackl
Christian Hackl

Reputation: 27528

Option 1: Make IBar itself a template class.

template <class T>
class Foo;

template <class T>
class IBar
{
public:
    virtual void placeFoo(Foo<T>& foo) = 0;
    virtual void removeFoo(Foo<T>& foo) = 0;
};

Option 2: Make all Foo<T> derive from a common, non-generic FooBase.

class FooBase
{
    // ...
};

template <typename T>
class Foo : public FooBase
{
public:
    Foo();
    ~Foo();
    //...
};

// ...

class FooBase;

class IBar
{
public:
    virtual void placeFoo(FooBase& foo) = 0;
    virtual void removeFoo(FooBase& foo) = 0;
};

The viability of both solutions depends on how much you actually depend on the T type. But that's what you should expect when you mix virtual functions with templates. With option 1, you do not have a common interface type anymore; with option 2, FooBase cannot provide any member function with a T-dependent argument.


By the way, don't forget about virtual destructors in your real code.

Upvotes: 1

Related Questions