Kevin W
Kevin W

Reputation: 21

Is there a decent alternative to dynamic_cast

I am working on a c++ project, and facing a design issue currently. I would appreciate it if someone can give me some suggestions. Basically, I have a base class Base, and a subclass Derived as below. Class Derived can do something that class Base cannot do.

class Base
{
public:
   virtual bool IsCapableOfDoingA() {return false;}
}

class Derived: public Base
{
public:
   bool IsCapableOfDoingA() {return true;}
   void DoA();
}

In another place where I have a pointer of type class Base.

void functionA(Base *pBase)
{
   if (pBase && pBase->IsCapableOfDoingA())
   {
      Derived *pDerived = static_cast<Derived*>(pBase);
      pDerived->DoA();
   }

}

Upvotes: 0

Views: 1184

Answers (4)

Mark Ransom
Mark Ransom

Reputation: 308158

Here's another idea. You can split the enhanced functions into an interface and have a method to return the interface pointer.

class InterfaceA
{
public:
    virtual ~InterfaceA() {}
    virtual void DoA() = 0;
};

class Base
{
public:
   virtual InterfaceA* GetAInterface() {return NULL;}
};

class Derived: public Base, InterfaceA
{
public:
   InterfaceA* GetAInterface() {return this;}
   void DoA();
};

void functionA(Base *pBase)
{
   InterfaceA* pA = pBase ? pBase->GetAInterface() : NULL;
   if (pA)
      pA->DoA();
}

Upvotes: 0

Michael Kristofik
Michael Kristofik

Reputation: 35188

In your design, is it ok for DoA to return a success code of some sort? You could replace IsCapableOfDoingA with DoA itself, and have the Base version simply return false (or other suitable error code). Child objects capable of doing A can override this function with a proper implementation.

You're right that dynamic_cast is often a design smell. With some more context we might be able to provide a better answer. My first thought is to really make sure a Derived IS-A Base if you're going to be polymorphically asking Bases for things they might not be able to do.

Upvotes: 2

Edward Loper
Edward Loper

Reputation: 15944

dynamic_cast will return NULL if the object doesn't have the appropriate type (assuming that the base class defines at least one virtual method -- usually you should at least make the base class's destructor virtual). So you can use the following idiom:

void functionA(Base *pBase)
{
   if (Derived *pDerived = dynamic_cast<Derived*>(pBase)) {
      pDerived->DoA();
   }    
}

If pBase doesn't have type Derived, then pDerived will be 0 (false), so the body of the if statement will be skipped.

Upvotes: 1

Mark Ransom
Mark Ransom

Reputation: 308158

The usual way is to add the function to the base class.

virtual void DoA() { throw std::runtime_error("Not implemented"); }

Upvotes: 4

Related Questions