tags:

views:

51

answers:

5

I'm extending a class provided by a third part library. The class, let's call it Foo, has a reset() method which can be called in order to restart Foo's behavior. The reset() method is also used internally by the class.

class Foo
{
  public:
    void reset () {
        /* ... */
    }
    void something () {
        reset();
    }
};

So far, I need to overload the reset() method in order to reset my additional features as well:

class Bar : public Foo
{
  public:
    void reset() {
        /* ...something... */
        Foo::reset();
    }
};

Unfortunately, since the Foo::reset() method is not virtual, by calling Bar::something() I get the Foo::reset() method called instead of Bar::reset().

Is there a way (different from overloading Foo::something() as well) to make it backward-virtual?

+4  A: 

You cannot extend classes that were not intended to be extended.

David Rodríguez - dribeas
+1  A: 

No this is not possible. The virtualness of a method is decided when the method is declared and you cannot change it later in a base class.

To allow you to do so would be nothing short of a disaster. Virtual methods simply behave differently than non-virtual methods and it must be accounted for when designing an object. With this proposal I would have to consider that all of my methods could behave in 2 distinctly different ways. That significantly adds to the design cost of the application and reduces the reliability.

JaredPar
+1  A: 

If neither reset nor something are virtual, you're screwed, and that's the end of the story. If something is virtual you could override it. However, if these necessary methods aren't virtual, then the class isn't intended to be extended (or implemented properly, if it was intended).

Edit:

You COULD try composition, e.g.

class Bar {
    Foo f;
    // foo's methods, etc, wrapped here
    void something() {
        f.reset();
        reset();
    }
};

But if you need the whole, implicit conversion, thing, you're still stuffed.

DeadMG
+2  A: 

You can't make reset() virtual in your library in such a way that it will affect the base class without changing the base class's code. For starters, the compiler has not added the necessary bookkeeping code that allows it to make virtual calls to reset().

Timo Geusch
+1  A: 

There is no 'clean way' of doing it using inheritance. Virtual is a compile/link time difference: using a vtable to resolve method at runtime (virtual) vs direct linking (non-virtual).

jv42