Wednesday, August 11, 2010

Overriding overloaded methods

#include <iostream>

using namespace std;

class B {
    public:
    virtual void A(string a, int b) {
        cout<<"B::A(string, int)"<<endl;
    }
    virtual void A(int c) {
        cout<<"B::A(int)"<<endl;
    }
};

class D : public B {
    public:
    virtual void A(string a, int b) {
        cout<<"D::A(string, int)"<<endl;
    }
};

int main() {
    D d;
    B* b = &d;
   
    b->A("a", 1);
    b->A(2);
   
    d.A("a", 1);
    d.A(2);

    return 0;
}

What do you think would be output of the above code?

Obviously, the output is not what most people will expect i.e.:
D::A(string, int)
B::A(int)
D::A(string, int)
B::A(int)


The code will instead give compilation error on line
     d.A(2);

This is because if you override one overloaded method, you need to override all of them, otherwise the ones you don't override are not available in the derived class.

To get things working you'll need to add following method in class D


virtual void A(int c) {
    B::A(c); 
}

As suggested by Kapil in the comments, the correct and elegant way to get it working is to add a declaration of A() in classD:

using B::A;

5 comments:

  1. Wow! I dint know that!! And I believe even the compilation error would have so informative as to we wont be able to made A or Z out of it!?!!

    Thanks for having this post included!

    ReplyDelete
  2. This comment has been removed by the author.

    ReplyDelete
  3. Very useful information, will save lot of frustration if you encounter this problem.
    This behavior is called Function Hiding, but not sure what is the use for this in C++, I don't think it is there in any of the other languages. I encountered this problem in my last project, I solved it by declaring the overloaded function of base class in the derived class with 'using' keyword just telling derived class that use all the overloaded functions from base, without the definition of the overloaded function in derived class. You can try that too.
    For your example it should be;

    class D : public B {
        public:
        virtual void A(string a, int b) {
            cout<<"D::A(string, int)"<<endl;
        }
      using B::A; // Will take all overloaded functions from base class
    };

    Do you have any idea why it has been in C++? Is there any scenario we should use this. I did not find much on internet about it :-(

    ReplyDelete
  4. Thanks for sharing Chetan!

    Thanks Kapil - you method is better :)

    ReplyDelete