Reputation: 4948
"I am sure there are tens of questions with the same title. Many of them are duplicate. Mine might be duplicate too, but I couldn't find any. So I try to make it very neat, short and simple."
I have an hierarchy like this:
class Shape {
public:
virtual void virtualfunc() { std::cout << "In shape\n"; }
};
class Circle: public Shape {
public:
void virtualfunc() { std::cout << "In Circle\n"; };
};
and when I use the classes with the help of pointer, the functions are called as I expected:
int main() {
Shape shape_instance;
Shape* ref_shape = &shape_instance ;
Circle circle_instance;
Circle* ref_circle = &circle_instance;
ref_shape = dynamic_cast<Shape*> (ref_circle);
ref_shape->virtualfunc();
}
Here the program calls the virtualfunc()
of the derived class and the result is naturally : In Circle
Now, I want to get rid of the pointers, use references instead, and get the same result. So I make trivial modifications to main()
to look like this:
int main() {
Shape shape_instance;
Shape& ref_shape = shape_instance;
Circle circle_instance;
Circle& ref_circle = circle_instance;
ref_shape = dynamic_cast<Shape&>(ref_circle);
ref_shape.virtualfunc();
}
But this time, the program calls the virtualfunc()
of the base class and the result is : In Shape
I appreciate if you let me know which concept of the references I am missing and how to change the references in the main() to get the result I got in the pointer version.
thank you
Upvotes: 15
Views: 2622
Reputation: 38586
If I understand correctly what you're trying to achieve/show (i.e. dynamic virtual function binding), perhaps this code will help:
#include <iostream>
using namespace std;
class Shape {
public:
virtual void virtualfunc() { std::cout << "In shape\n"; }
};
class Circle: public Shape {
public:
void virtualfunc() { std::cout << "In Circle\n"; };
};
int main() {
Circle circle_instance;
// don't care what kind of Shape
Shape &someShape = circle_instance;
someShape.virtualfunc();
}
Here you can see that someShape
can be bound to Shape
or any derived class and the virtual function will be called on the actual dynamic type. This will print In Circle
. Proof: http://ideone.com/A1UvrR
There's no need for dynamic_cast
Upvotes: 1
Reputation: 208343
References cannot be reseated. Once you initialize the reference in the initialization, it becomes an alias to the referred object and cannot be distinguished from it. The latter assignment:
ref_shape = dynamic_cast<Shape&>(ref_circle);
really means:
shape_instance = dynamic_cast<Shape&>(ref_circle);
You can, on the other hand, bind a new reference to the object (and you don't need the dynamic_cast
, as the conversion from reference to derived to reference to base is implicit):
Shape & another_ref = ref_circle;
another_ref.virtualfunc(); // Dispatches to Circle::virtualfunc
Upvotes: 18
Reputation: 63775
This is where your Circle
is turning into a Shape
.
ref_shape = dynamic_cast<Shape&>(ref_circle);
// ^ here
ref_shape.virtualfunc();
ref_shape
has already been defined to be a reference to shape_instance
.
You are not copying the reference itself, since references cannot be reassigned. You are copying the actual object to a Shape
object. It's getting stored in shape_instance
.
You can verify this by trying this code. It will print In Circle
.
dynamic_cast<Shape&>(ref_circle).virtualfunc();
Upvotes: 6
Reputation: 23634
You should do the following:
#include <iostream>
class Shape {
public:
virtual void virtualfunc() { std::cout << "In shape\n"; }
};
class Circle: public Shape {
public:
void virtualfunc() { std::cout << "In Circle\n"; };
};
int main() {
Shape shape_instance;
//Shape& ref_shape = shape_instance;
Circle circle_instance;
Circle& ref_circle = circle_instance;
Shape& ref_shape = dynamic_cast<Shape&>(ref_circle);
ref_shape.virtualfunc();
}
It outputs in Circle as you expected.
Upvotes: 4