0

Hello,

I have a question regarding downcasting of base class pointers. I am providing a sample class design which is similar to my program.

class A
{
  protected:
  double num1;

  public:
  virtual void fn1() = 0;
};

class B:public class A
{
  protected:
  double num2;

  public:
  virtual void fn1();  // performs some operation on num1
  void fn2();          // performs some operation on num2
};

class C:public class A
{
  protected:
  double num3;

  public:
  virtual void fn1();  // performs some operation on num1 and num3
};

int main()
{
   A *a1, *a2;
   
   a1 = new B;
   a2 = new C;

   // downcasting here
   B *b = dynamic_cast<B *>(a1);
   b->fn2();

   a2->fn1();
}

The function fn2() and num2 are specific to class B and it wouldn't make sense to have them in the base class. The question is there any change that I can do in the class design to prevent this downcasting the base class pointer? In some forums and book, it is said that downcasting indicates poor design. I feel in this kind of situation downcasting can't be avoided. Am I right in assuming this?

Thanks in advance,

2
Contributors
1
Reply
2
Views
5 Years
Discussion Span
Last Post by jinhao
1

In this situation, it can't be avoided. But why does the situation exist? I change your code like this.

void operate_fn2(A * p)
{
    B * b = dynamic_cast<B*>(p);
    if(b)
        b->fn2();
}

int main()
{
    A *a1, *a2;
 
    a1 = new B;
    a2 = new C;
 
    // downcasting here
    operate_fn2(a1);
 
    a2->fn1();
}

Is there a routine that calls operate_fn2 with a pointer refers to the object which type is not B?
Answer: YES
operate_fn2 can receive all objects that derived from A, but only B can be operated. It means you know what derived class will be created in your class hierarchy, and what the new method will be inserted to you derived class. That I can say the new derived class has a new behaviour called fn2, the operate_fn2 determines through the new behaviour. In this situation, I always put fn2 to the base class.

class A
{
....
public:
    virtual void fn1() = 0;
    virtual void fn2() = 0;
};

void operate_fn2(A * p) //A general method for A.
{
   p->fn2();
}

On the other hand, answer: NO
The type of object that is passed to operation_fn2 is class B absolutely. It means this routine is desgned for class B and it executes only if the object is created. In this situation, I usually do it like this.

void operate_fn2(B * b) //Just for B
{
    b->fn2();
}

void routine_A(A* p) //A general method for A
{
   p->fn1();
}

int main()
{
    A *a2;
 
    B* b = new B;
    //go to the routine that operate B
    operate_fn2(b);

    a2 = new C;
 
    routine_A(b);
    routine_A(a2);
}

Hope this helps you.

Votes + Comments
simple and effective explanation
This topic has been dead for over six months. Start a new discussion instead.
Have something to contribute to this discussion? Please be thoughtful, detailed and courteous, and be sure to adhere to our posting rules.