i dont see the point or why you would ever want to upcast an object for example

class Shape
{
.....
};


class rectangle : public shape
{
....
};


int main()
{
rectangle object1;
Shape *shapePtr = &object1;

return 0;
}

Having a collection of Shapes would be terribly difficult if you has to have a separate container for each type of Shape you had. Casting to a Shape pointer allows you to store any type of Shape in a single container and still have it operate appropriately.

Well, obviously, your example is a straw-man, you would not want to upcast in that case.

One of the main points of Object-Oriented Programming is the concept of Polymorphism, which entirely relies on upcasting and virtual member functions. If you are not familiar with virtual functions, it is almost pointless to convince you of the purpose of upcasting. In your example, you could have:

class shape {
  public:
    virtual double getArea() const = 0; //virtual function to compute the area.
    virtual ~shape() { }; //don't forget to make the destructor virtual in the base class.
};

class rectangle : public shape {
  private:
    double width, length;
  public:
    virtual double getArea() const { return width * height; };
};

class circle : public shape {
  private:
    double radius;
  public:
    virtual double getArea() const { return 3.14159 * radius * radius; };
};

int main() {
  std::vector< shape* > v;
  v.push_back(new rectangle());
  v.push_back(new rectangle());
  v.push_back(new rectangle());
  v.push_back(new rectangle());
  v.push_back(new circle());
  v.push_back(new circle());
  v.push_back(new circle());
  v.push_back(new circle());
  
  double totalArea = 0;
  for(std::vector< shape* >::iterator it = v.begin(); it != v.end(); ++it)
    totalArea += (*it)->getArea();
  std::cout << "total area of all shapes is " << totalArea << std::endl;

  for(std::vector< shape* >::iterator it = v.begin(); it != v.end(); ++it)
    delete *it;
  return 0;
};

The point in the above example is that the vector of shapes can hold any kind of shapes (rectangles, circles, what have you), and not care of what kind of class they are, because all that is needed is access to the few (virtual) functions that the shape class provides (getArea() in this case). This is called polymorphism, objects that are of class rectangle or circle or whatever can act as just "shape" objects, or alternatively, from the other point of view, any objects that you store by reference to a "shape" class can act with code specific to any of the derived classes.

Edited 5 Years Ago by mike_2000_17: n/a

Comments
Good post, as always

Mike already gave an excellent example.

Just to point out in different words. In a good design you want abstraction. And that's provided by inheritance (among other options) primarily.
As long as users use abstractions (Shape in this case) they're shielded from implementation details.
A good example from "Java" is:

class MySingleThreadedApplication {
   public static void main(String[] arg) {
      Map<Sting> m = new HashMap<String>();
      do_something_with_map(m);
   }

   public static void do_something_with_map(Map<Sting> zMap) {
      // do something..
   }
}

Here the function do_something_with_map() "upcasts" the object. HashMap is not synchronized. There is another implementation of Map available HashTable, viz. sync'd.
Now if tomorrow you need synchronization in your application, you just have to change line 3 in this example to: Map<Sting> m = new Hashtable<String>(); This is possible because do_something_with_map() uses abstraction (Map) instead of implementation (HashMap).

Similar example from C++ world would be the hierarchy of iostream classes. You can write generic function read_write(iostream& zStream) that reads/writes to a file (fstream) or a string (stringstream) .

This article has been dead for over six months. Start a new discussion instead.