Reputation: 59
Please see the following simple code:
class A
{
public:
A() {}
virtual bool cmp(const A& a) const {cout << "cmp A" << endl; return true;}
};
class B : public A
{
public:
B() {}
~B() {}
bool cmp(const B& b) const {cout << "cmp B" << endl; return false;;}
};
int main()
{
A a1;
A a2;
B b1;
B b2;
a1.cmp(a2); // as expected
b1.cmp(b2); // as expected
a1.cmp(b1); // upcasting
// b2.cmp(a2); // conversion needed
// Here is the problematic part:
A* pa;
pa = new B;
pa -> cmp (b1); // Why why why the cmp of A runs?
return 0;
}
I just can't understand it - there is vptr and vtbl and a function that matches exactly to the call, without any casting. So why is cmp of class A is called?
Any logical answer will be much appreciated.
Upvotes: 1
Views: 117
Reputation: 15075
Note that while co-variant return types are allowed in the overriding virtual function, co-variant argument types are not! So you hide the base virtual function, instead of overriding it.
Upvotes: 0
Reputation: 12904
You have two overrides
A::cmp(const A&)
B::cmp(const B&)
So when you do pa->cmp()
It calls A::cmp
because type of pa is A at compile time. and there is no point of vptr here because you are not overriding anything at all.
It will be overriding If you have
bool B::cmp(const A& b)
which overrides the signature A::cmp(const A& b)
Upvotes: 1
Reputation: 47482
Your method on B is 'hiding' the base class method, so you can't see it through B. See the C++ FAQ for a more detailed explanation.
Upvotes: 0
Reputation: 9089
Because B::cmp()
signature is different from A::cmp()
. So B::cmp()
is NOT overriding A::cmp()
, but hiding it, it's not virtual and doesn't known by call through A*
.
Upvotes: 0
Reputation: 10541
Well, that's expected, because bool cmp(const B& b) const
doesn't override a virtual method of the base class, since they have different signatures.
Upvotes: 0
Reputation: 24846
Because A::cmp
and B::cmp
signatures does not match.
And b1
is first converted to const A &
and A::cmp
is called
Upvotes: 1
Reputation: 258638
Because you're not overriding the operator. You have 2 different operators in your classes.
To override a method or operator, the signature has to match perfectly. That means:
The base class operator takes a const A&
as parameter, the derived class takes a const B&
.
Upvotes: 3