Question

The purpose of an abstract class is not to let the developers create an object of the base class and then upcast it, AFAIK.

Now, even if the upcasting is not required, and I still use it, does it prove to be "disadvantageous" in some way?

More clarification:
From The Thinking in C++:

Often in a design, you want the base class to present only an interface for its derived classes. That is, you don’t want anyone to actually create an object of the base class, only to upcast to it so that its interface can be used. This is accomplished by making that class abstract,

By upcasting, I meant: baseClass *obj = new derived ();

Was it helpful?

Solution

Upcasting can be disadvantageous for non polymorphic classes. For example:

class Fruit { ... };  // doesn't contain any virtual method
class Apple : public Fruit { ... };
class Blackberry : public Fruit { ... };

upcast it somewhere,

Fruit *p = new Apple;  // oops, information gone

Now, you will never know (without any manual mechanism) that if *p is an instance of an Apple or a Blackberry.

[Note that dynamic_cast<> is not allowed for non-polymorphic classes.]

OTHER TIPS

Abstract classes are used to express concepts that are common to a set of (sub-)classes, but for which it is not sensible to create instances.

Consider a class Animal. It does not make sense to create an instance of that class, because there is no thing that is just an animal. There are ducks, dogs and elephants, each of which is a subclass of animal. By formally declaring the class animal you can capture the similarities of all types of animals, and by making it abstract you can express that it cannot be instantiated.

Upcasting is required to make use of polymorphism in statically typed languages. This is, as @Jigar Joshi pointed out in a comment, called the Liskov Substituion Principle.

Edit: Upcasting is not disadvantageous. In fact, you should use it whenever possible, making your code depend on super-classes(interfaces) instead of base-classes(implementations). This enables you later switch implementations without having to change your code.

Upcasting is a technical tool.

Like every tool it is useful when used correctly and dangerous / disadvantageous if used inconsistently.

It can be good or bad depending on how "pure" you want your code to be in respect to a given programming paradigm.

Now, C++ is not necessarily "pure OOP", not necessarily "pure Generic", not necessarily "pure functional". And since C++ is a "pragmatic language", it is not in general an advantage force it to fit a "one and only paradigm".

The only thing that can be said, in technical terms, is that,

  • A derived class is a base class plus something more
  • Referring a derived through a base pointer makes that "something more" not accessible, unless there is a mechanism in the base to make you jump into the derived scope.
  • The mechanism C++ offers for that implicit jump are virtual functions.
  • The mechanism C++ offers for explicit jump is dynamic_cast (used in downcasting).
  • For non-polymorphic objects (that don't have any virtual method) static_cast (to downcast) is still available, but with no runtime check.

Advantages and disadvantages derive from consistent and inconsistent use of all of those points together. Is not a matter related to downcast only.

One disadvantage would be the obvious loss of new functionality introduced in the derived class:

class A
{
   void foo();
}

class B : public A
{
   void foo2();
}

A* b = new B;
b->foo2(); //error - no longer visible

I'm talking here about non-virtual functions.

Also, if you forget to make your destructors virtual, you might get some memory leaks when deleting a derived object via a pointer to a base object.

However all these can be avoided with a good architecture.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top