Eva
Eva

Reputation: 59

casting and polymorphism

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

Answers (7)

Igor R.
Igor R.

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

Neel Basu
Neel Basu

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

Rob Walker
Rob Walker

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

Rost
Rost

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

Maksim Skurydzin
Maksim Skurydzin

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

Andrew
Andrew

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

Luchian Grigore
Luchian Grigore

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:

  • name
  • parameters
  • cv-qualifiers

The base class operator takes a const A& as parameter, the derived class takes a const B&.

Upvotes: 3

Related Questions