I have a result that I didn't expect from multiple inheritance, virtual
methods and pointers to base classes.
With d.getStr()
, when d
is a derived
instance, the base_2
version is called, as I expected.
With p->getStr()
, when p
is a pointer to a derived
instance (or a pointer to base_2
pointing to a derived
instance), the base_2
version is called, as I expected.
But with p->getStr()
, when p
is a pointer to a base_1
pointing to a derived
instance, the base_1
version is called and I was convinced would be called the base_2
version (thanks the using
and the fact that getStr()
are virtual
methods).
The following is a simple example:
#include <iostream>
struct base_1
{
virtual std::string getStr () const
{ return "string from base 1"; }
};
struct base_2
{
virtual std::string getStr () const
{ return "string from base 2"; }
};
struct derived : public base_1, public base_2
{
using base_2::getStr;
};
int main ()
{
derived d;
derived * dp = &d;
base_1 * bp1 = &d;
base_2 * bp2 = &d;
std::cout << "from derived: " << d.getStr() << std::endl;
std::cout << "from derived pointer: " << dp->getStr() << std::endl;
std::cout << "from base_1 pointer: " << bp1->getStr() << std::endl;
std::cout << "from base_2 pointer: " << bp2->getStr() << std::endl;
}
The output is the following
from derived: string from base 2
from derived pointer: string from base 2
from base_1 pointer: string from base 1
from base_2 pointer: string from base 2
I know that, to impose the call of base_2
version, I can add in derived
the following method
std::string getStr () const
{ return base_2::getStr(); }
but my questions are:
1) Why does the pointer to base_1
(pointing to a derived instance) ignore the using
directive and call the base_1
version of getStr()
?
2) Is there a way to impose the base_2
version of getStr()
, when derived
instance is used by a base_1
pointer, without redefining getStr()
?
--- EDIT ---
Thanks for the answers.
I understand that you are describing what's happening but my doubt is: does the language (the standard) describe this aspect? Or is it an undefined part?
I mean: if I remove the using
directive, I get a compilation error (error: request for member getStr is ambiguous
), from d.getStr()
and from dp->getStr()
, because the compiler doesn't know which version of getStr()
to chose.
But getStr()
are virtual
methods. So (I was convinced that) a base pointer should use the derived version of they. But we have a couple of colliding methods.
From the language (standard) point of view, a base_1
(or base_2
) is the pointer authorized (or obligated) to choose one of the two versions of the colliding methods ignoring the other?
Maybe I'm wrong but seems to me that, in this way, the virtual
methods are managed as non virtual
methods.