Virtual function calling using dereference object
I have a base class pointer pointing to a derived class object. I am calling foo()
function by using two different ways in the code below. Why does Derived::foo()
get called in the first case? Shouldn't (*obj).foo()
call Base::foo()
function as it has already been dereferenced?
class Base
{
public:
Base() {}
virtual void foo() { std::cout << "Base::foo() called" << std::endl; }
virtual ~Base() {};
};
class Derived: public Base
{
public:
Derived() : Base() {}
virtual void foo() { std::cout << "Derived::foo() called" << std::endl; }
virtual ~Derived() {};
};
int main() {
Base* obj = new Derived();
// SCENARIO 1
(*obj).foo();
// SCENARIO 2
开发者_开发问答 Base obj1 = *obj;
obj1.foo();
return 0;
}
// SCENARIO 1 (*obj).foo();
Note that
obj
is a misnomer here, since it doesn't refer to an object, but to a pointer,(*ptr).foo()
is just a roundabout way to doptr->foo()
.
*ptr
doesn't result in an object, but in a reference Base&
to the object. And a virtual function call through a reference is subject to dynamic dispatch, just as such a call through a pointer.
// SCENARIO 2 Base obj1 = *ptr; obj1.foo();
What you do here is you create a totally new object through slicing: it just has the base class parts of *ptr
. What you want instead is this:
Base& ref = *ptr;
ref.foo();
Scenario 2 creates an entirely new object of type Base. As such, when we do obj1.foo()
, the object isn't Derived at all; there's no way we'll call the Derived function.
In scenario 1, however, the object is, in truth, an instance of Derived, which we're accessing through a Base pointer. This is exactly the situation virtual functions are designed for; the derived class's implementation is used.
It helps if you think a little bit about the implementation. In the second scenario you're actually creating a new object of type Base which will come with a new virtual function table. But in the first scenario *obj
will "point to", or rather reference, an object which still has the virtual function table of an object of type Derived.
As an addition to other answers.
The technical term for what is happening in your Scenario 2 is object slicing.
Here's the wikipedia entry:
http://en.wikipedia.org/wiki/Object_slicing
And here's another question on stackoverflow on object slicing:
What is object slicing?
In first case the derived version of foo()
will be called due to the obvious reasons explained above. In addition to other answers the *(*Obj).func()*
is synonymous to *Obj->func()*
.
In second case a new object of class Base
is being instantiated through the copy constructor and since it's a Base
class object it will call the Base
class version of foo()
.
Polymorphism works on references (the result of dereferencing a pointer) just as it does on pointers.
What do yo mean by "as it has already been dereferenced "?
The base class pointer obj is pointing to derived class object and since you have declared the function foo() virtual the derived class foo() will be called.
(It is rather strange question. I would rather expect someone ask why in the second case Derived::foo
is not called.)
In C++ language, which version of virtual function is called is completely independent of what has and what has not been "dereferenced". Dereferencing makes no difference whatsoever. The only thing that matters is the dynamic type of the object used in the call.
In the first case Derived::foo
is called because the dynamic type of the *obj
object is Derived
.
In the second case the dynamic type of obj1
is Base
, so the Base::foo
is called.
In other words, everything works as expected. Which makes one wonder wat made you ask your question. What made you to expect something different?
精彩评论