Bertramp
Bertramp

Reputation: 385

How to use functions from derived class without adding them to the base class

This is very likely a silly question, but I can't seem to figure out if this is at all possible and if it should actually be done.

Say some code relies a lot on using a certain virtual base class acting as an interface and then deriving several subclasses that implements the virtual methods the base class. Is it possible to use functionality not exsisting in the base class (interface) below without completely disregarding the solid principles, when the rest of the program must not see anything but the base class "interface"? Like in the example below, is it possible to use bar() from the B class inside the function that only knows of A? And should I just add bar() to the "interface" instead?

// Base class - "interface"
Class A
{
    public:
        virtual int foo();
}

// Derived class - implementing the "interface" + more
Class B: public A
{
    public:
        int foo();
        int bar();
}

int main()
{

    function(A); // Some magic function that would utlize the bar() method

    return 0;
}

Upvotes: 0

Views: 193

Answers (1)

Peter Ruderman
Peter Ruderman

Reputation: 12485

The short answer is yes, use the dynamic_cast operator (but see below). The magic function would look something like this:

void function(A& a)
{
  B* b = dynamic_cast<B*>(&a);
  if (b)
  {
    // Object is a B...
    b->bar();
  }
  else
  {
    // fallback logic using only methods on A
  }
}

But be aware that many programmers consider this a code smell. In particular, if there's no way to implement the "fallback" branch, then it suggests the function should really accept a B and something in the design may be amiss. (It's hard to say when talking in such generalities, however.) Also be aware that dynamic_cast can be expensive, particularly with complex class hierarchies.

If at all reasonable, it's preferable to move the B-specific logic into the B class somehow. You might also consider making the bar method a member of the A class (A would provide some sensible default implementation). Another approach might be to create a new interface to hold the bar method and have your function accept an object of that type. (The B class would implement both A and the new interface.)

Upvotes: 1

Related Questions