The main reason for the usage of them is to make polymorphism possible. Another technique that is needed for polymorphism is late/dynamic binding.
Upcasting allows us to use inherited classes (sub-classes) with the base class interface. You can handle those object with the same base class interface without need to know what concrete child class object it is.
On the other hand, downcasting is needed because you may want to get the special methods or member variables of a child object. Then, you need to downcast.
To cast up or down you can safely use the dynamic_cast which is described here.
If the cast is successful, dynamic_cast returns a value of type new_type. If the cast fails and new_type is a pointer type, it returns a null pointer of that type. If the cast fails and new_type is a reference type, it throws an exception that matches a handler of type std::bad_cast.
To up or downcast between base and child class you need either a pointer (type*) or a reference type (type&) because only the view to the object changes not the concrete object itself. If you use the object itself object slicing would occur and you would lose information of an inherited class.
I give you one example when to use up- and downcasting. Consider you have a parent class Car and 2 classes Porsche and Ford that are inherited from Car. Now you have a std::vector<Car*> cars for example where you want to put in different cars. You would do something like:
std::vector<Car*> cars;
cars.push_back(new Porsche()); /* implicit upcast */
cars.push_back(new Ford()); /* implicit upcast */
The benefit is you have one vector of "different" objects, it's possible because both have the same parent class.
If you now want to get those cars you can do:
Car* porscheAsCar = cars.at(0);
Porsche* porsche = dynamic_cast<Porsche*>(cars.at(0));
Now for example the Car class does have a drive() method and the Porsche class a driveFast() method implemented. You would access them:
porscheAsCar->drive(); /* Call Porsche drive() method */
porsche->drive(); /* Call Porsche drive() method */
porsche->driveFast(); /* Call Porsche driveFast() method */
Even though we call the drive method with the base class interface it will be the drive method of the Porsche, if the method is declared with virtual. With the downcast you can access the methods/member variables that are specific for the inherited class. But it is just possible if the Car is really a Porsche and not a Ford for example.
Full example with some output on ideone see here.