5
#include <iostream>
class base
{
    public:
    virtual void print (int a)
    {   
        std::cout << "a: " << a << " base\n";
    }   
    virtual void print (int a, int b)
    {   
        std::cout << "base\n";
    }   
};

class derived : public base
{
    public:
    virtual void print (double d)
    {   
        std::cout << "derived\n";
    }   
};

int main ()
{
    int i = 10; 
    double d = 10000.0;
    base *b = new derived (); 
    b->print (i, i); 
    b->print (d);

    return 0;
}

The output of this function is:

base
a: 10000 base
  • Why b->print (d) don't invoke the derived class implementation and performs static cast on 'd' to provide a match with base class implementation ?
  • What rule is applied here during virtual function lookup ?
iammilind
  • 68,093
  • 33
  • 169
  • 336
lava
  • 1,945
  • 2
  • 14
  • 15
  • 3
    You're working with the type base, not derived. It doesn't have a function which takes a double, so it's casting to int to find the best match. – Rob Mar 21 '11 at 00:33

3 Answers3

8

derived::print does not override any member function in base. It is declared as having a single parameter of type double but the two virtual member functions named print in base are declared as having one and two parameters of type int.

When you use b->print(d), only member functions in base are considered during overload resolution, so only void base::print(int) and void base::print(int, int) are considered. void derived::print(double) can't be found because the compiler has no idea that b points to a derived object.

If derived were to override one of the two print functions declared as virtual member functions in base, then that override would be called at runtime.

(On a somewhat related note, derived::print hides the two base::print member functions, so if you were to try to use one of the base class print functions, e.g., derived().print(1, 1), it would fail. You would need to use a using declaration to make those member functions available during name lookup.)

James McNellis
  • 348,265
  • 75
  • 913
  • 977
1

Overload resolution happens at compile time. Overrides happen at run time.

Therefore, the overload resolution of b->print(d); happens first. This selects Base::print(int) because it's the only one-argument print.

At runtime, b points to a Derived object that has no override for Base::print(int). Therefore, Base::print(int) is still called.

MSalters
  • 173,980
  • 10
  • 155
  • 350
0

Because double can be automatically converted to an int in the first definition it sees (in the base class)

See explicit keyword or this question

Community
  • 1
  • 1
Martin Beckett
  • 94,801
  • 28
  • 188
  • 263