#include "stdafx.h"
#include<iostream>


using namespace std;

class Shape
{
public:
   virtual void fun()
   {
	   cout<<"in base"<<endl;
   }
};

class Square:public Shape
{
	public:
   void fun()
   {
	   cout<<"in Square"<<endl;
   }

};

class Circle:public Shape
{
	public:
   void fun()
   {
	   cout<<"in Circle"<<endl;
   }

};


int _tmain(int argc, _TCHAR* argv[])
{  
	Shape *s=new Shape();    
	s->fun(); 
	Circle *Sq=(Circle *)s;
	Sq->fun(); 
	system("pause");
	return 0;
}

Output:
In BAse
In BAse


can anyone tell me why it didn't called the fun() of Circle ,as i type casted the Shape object to circle.

TIA

Recommended Answers

All 6 Replies

What you are doing should not be done. It may even cause runtime exceptions in some cases.Know this always "A base class pointer can be used(by typecasting) to point to a base class object or a derived class object but the reverse should never be done."

The reasoning for above is that using a derived class pointer you may try to access the functions you have added(extra) to the derived class after inheriting from the base class. This is a strict violation if the object you are pointing to is a base class object.

Try this instead :
Firstly remove the virtual tag in shape.

Circle *c = new Circle();
c->fun();
Shape *s = (Shape *)c;
s->fun();

You will get the result you are expecting.

Part of the problem here is you are using an unsafe C-style cast. Also because you have a virtual function in your base class you're dealing with polymorphism.
When attempting to cast polymorphic types, you need to enable RTTI (Run Time Type Information) in your project and use the dynamic_cast operator to cast pointers between polymorphic types in a safe manner.

How you enable RTTI will vary depending on the compiler/IDE you're using.
Typically in VS you go to your project properties and in the 'C/C++ -> language settings' tab you set the 'Enable Run-Time Type Info' item to Yes.
Or you can go to the 'C/C++ -> Command line' tab and add the /GR switch to the additional options. If you're using another Compiler/IDE, you may have to consult your manual!

The dynamic_cast operator attempts to cast one type to another, but if the cast fails, it returns a null pointer. Which is far safer than using the C-style cast which will cast the pointer/object regardless of whether it is valid or not!

Also, with your classes you need to take note that an instance of a Circle can be considered to be a valid instance of a Shape, so casting from a Circle pointer to a Shape pointer should work, but the converse is not necessarily true. A Shape pointer doesn't necessarily point to a Circle, it could be pointing to a Square, or any other Shape derived class. It could even just be a plain old Shape! Which is something you need to bear in mind when casting between polymorphic types!

In your posted code, you've created a Shape pointer to point to a new Shape and then used a C-style cast to cast the pointer to a Circle. The C-style cast is not type-safe and will cast the Shape pointer to a Circle pointer, but the reason that Shape.fun() is called and not Circle.fun() is because the object the pointer is pointing to is a Shape and NOT a Circle (despite the cast). In fact if anything, what happens in this case is more likely to be undefined behaviour!

If you used dynamic_cast you'd see that the cast fails because the Shape being pointed to is not an instance of a Circle, it is actually an instance of the base class Shape!

So if you try this in your main function:

int main()
{
    Shape *s = new Shape();
    s->fun();
    // attempt to cast using dynamic_cast
    Circle *Sq = dynamic_cast<Circle*>(s);
    if(Sq)
        Sq->fun()
    else
        cout << "Unable to cast from Shape to Circle!" << endl;
    return 0;
}

When you attempt to cast Shape s to a Circle, you will see the message "Unable to cast from Shape to Circle"


However, you could have a Shape pointer which points to a Shape derived object like a new Circle and then cast the pointer from a Shape pointer to a Circle pointer.

The following code demonstrates what I mean:

int main()
{
	//Create a Shape pointer which points to a new Circle
	// Note: Because a Circle IS a Shape the pointer will be OK
	Shape *shape = new Circle();
	shape->fun(); // will output "in Circle" NOT "in Base"! Explanation in main post	

	// Now let's attempt to cast the Shape pointer (shape) to a Square pointer
	// This should fail because the shape points to an instance of a Circle NOT a Square
	Square *square = dynamic_cast<Square*>(shape);
	if(square )
		square ->fun(); // Won't be called
	else // this will:
		cout << "Unable to convert the Shape* to a Square* !" << endl;

	// Now lets try casting shape to a Circle*
	// This should succeed because the Shape pointer sh points to a Circle!
	Circle *circle = dynamic_cast<Circle*>(shape);
	if(circle)
		circle->fun(); // will output "in Circle"
	else
		cout << "Unable to convert from Shape* to Circle*!" << endl;
	return 0;
}

The output from the above code would be:

in Circle
Unable to convert the Shape* to a Square* !
in Circle

Now I know what you're wondering...When we pointed the Shape pointer (shape) to the new instance of a Circle, why did the call to shape->fun() call the Circles function rather than the base-class version? This is because the object pointed to by the Shape pointer (a Circle) has it's own overridden version of fun(). The base-class version of a function will only be used by a derived class if it does not have an overridden version of its own.
So because Circle.fun() overrides Shape.fun(); Circle.fun() will always be used, regardless of whether a pointer to a Circle is a Circle pointer or a Shape pointer!

In order to call the base class version of fun() you need to explicitly call it.
e.g.

shape->Shape::fun():

OR

if(circle)
    circle->Shape::fun();

I hope this clears things up for you!

commented: Nice post. +14

Thanks 4 reply !!

i know how to do safe downcasting ,but my question is when i typecasted the base object to derived then pointer should call the fun() of derived (from virtual function call mechanism )

correct me if i am wrong !!
TIA

No, because the base object does not have any of the properties of the derived object.

Shape is your base class. You set up a pointer to point to a new instance of your Shape class. And although you cast your Shape pointer to a Circle pointer using an unsafe C-style cast, the Shape class does not contain any of the properties of a Circle, or any other derived class for that matter!
A base class object simply cannot be cast to a derived class object.

You can cast a derived object pointer to a base object pointer and back again. You can set a base object pointer to point to a new derived object and then cast the base class pointer to the appropriate type.

But you cannot set a base object pointer to point to a new base class instance and then cast it to a derived object pointer! It simply doesn't work that way!

Any instances of any of your Shape derived classes (Circle, Square etc) can safely be considered as valid Shape objects and as such can be cast safely.
But an instance of a Shape object cannot be cast to any derived type.

I'm sure somebody like Narue could put this far more succinctly than my somewhat chaotic fumbling attempt, but that's about the short of it!

If you want to do the more dangerous C-style casting, then CSurfer has it pretty much covered in his post. If you lose the virtual keyword (and hence lose the polymorphism) then his example of creating a Circle pointer and then C-style casting it back to a Shape pointer would allow the Shape pointer to use the Shape::fun() function and the Circle pointer to use Circle::fun() function. Even though both pointers are pointing to the same Circle object.
But again, you can't do it the other way around. You still can't cast a base object to a derived object.

when i typecasted the base object to derived then pointer should call the fun() of derived (from virtual function call mechanism )

When working with polymorphism there are two types in action:

  • Actual Type: The type of the object itself
  • Virtual Type: The type of the pointer or reference you're using to access the object

The actual type does not change after instantiating an object, but you can access it through different virtual types. The idea behind polymorphism is to access the actual type's overridden member functions from the virtual type's matching interface. So let's look at your example:

Shape *s = new Shape();    
s->fun();

You've instantiated a Shape object and access it through a pointer to Shape. Both the actual and virtual types are Shape. When you call s->fun() , you'll get Shape's instance of fun.

Circle *q = (Circle*)s;
q->fun();

You've cast the virtual type from Shape to Circle and assigned the result to a pointer to Circle (the safety of this cast is irrelevant). The virtual type is now Circle, but the actual type is still Shape. Calling q->fun() will continue to get Shape's instance of fun.

The key is to recognize that casting a Shape to a Circle doesn't change the Shape object to a Circle object, it only changes how you perceive the Shape object. This is why the cast is unsafe, because if you perceive something that isn't there, any number of bad things can happen. Down-casting can produce a form of slicing, where part of the object is invalid.

i know how to do safe downcasting ,but my question is when i typecasted the base object to derived then pointer should call the fun() of derived (from virtual function call mechanism )

correct me if i am wrong !!

OK, you're wrong.

If D is derived from B, and you want to cast a B* object to D*, then the B* object must be pointing to a D* object, or to an object of a type derived from D*, or the pointer must be zero. If none of these conditions applies, the program's behavior is undefined.

So you did something for which the behavior is undefined. In that case, the implementation is allowed to do as it pleases, and it is a waste of time trying to explain why it did what it did.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.