I wrote the following piece of code to test my understanding of virtual inheritance. Apparently, I still don't get it fully. Here is my code (followed by my question):
#include <iostream>
#include <vector>
using namespace std;
class Foo
{
public:
virtual void foo();
void foo2();
};
void Foo::foo()
{
cout << "In FOO - foo 1" << endl;
foo2();
}
void Foo::foo2()
{
cout << "In FOO - foo 2" << endl;
}
class Bar : public Foo
{
public:
void foo();
void foo2();
};
void Bar::foo()
{
cout << "In BAR - foo 1" << endl;
foo2();
}
void Bar::foo2()
{
cout << "In BAR - foo 2" << endl;
}
int main()
{
Foo* f = new Foo;
f->foo();
Foo* b = new Bar;
b->foo();
return 0;
}
This is my understanding:
The pointer f points to the base class Foo and f->foo()
calls foo()
in the base class which in turn calls foo2()
in the base class.
The pointer b is a base-class pointer but points to an object of the derived class Bar. Now, since foo()
is a virtual function, it calls foo()
of the derived class. Now foo()
(of the derived class) calls foo2()
. Since foo2()
is not a virtual function, I was expecting the base class foo2()
to get called. However I see that foo2()
of the derived class is getting called.
So, I was expecting this output:
In FOO - foo 1
In FOO - foo 2
In BAR - foo 1
In FOO - foo 2
but got this instead:
In FOO - foo 1
In FOO - foo 2
In BAR - foo 1
In BAR - foo 2
Why is this so? From what I understand, the vtable will have an entry only for foo()
and not for foo2()
. So, how is foo2()
of the derived class getting called?
This is my first post. Please excuse me if I have broken any posting guidelines. Thanks in advance!
In
Bar::foo()
, you are callingfoo2()
. This is really equivalent to callingthis->foo2()
. The type ofthis
isBar
, so this is really equivalent to:So there's no polymorphism involved at this point; the call is resolved to
Bar::foo2
at compile-time, rather than dynamically at run-time.This is because
Bar::foo2()
is thefoo2()
called byfoo()
.Bar::foo2()
is local toBar::foo()
and has precedence. It's just static dispatch fromBar::foo2()
.If the behavior you expected is what you really want, you can choose the method by specifying its scope like so:
So this really does not have to do with dynamic dispatch.
You expect Bar::foo2 to never be called. Then your question can be reformulated as: "why is the purpose of Bar::foo2, if any?"
Its purpose is to be called when dealing with Bar objects. The foo2 of a Bar object is called whenever foo2 is called.
It is only for foo objects that it matters whether Foo::bar2 is virtual or not. Inheritance never forces you to use the functions with the same signature in the base class, if you are dealing directly with derived class objects. (It would cause too many unpleasant surprises to have the inheritance rules work differently in this matter.)
What you have essentially done is hiding. By creating a function with the same signature in Bar, you have hidden the nonvirtual function in the base class Foo. This is typically a bad design because it is unnecessarily complex - it is better to choose different names for different things, to avoid hiding. Hiding is seldom part of a conscious good design.
because Bars foo is what's calling foo2, at that stage it knows its a Bar....
try again, except call foo2 directly in main for both rather than foo calling foo2