C++ overload resolution

12,406

Solution 1

The two “overloads” aren't in the same scope. By default, the compiler only considers the smallest possible name scope until it finds a name match. Argument matching is done afterwards. In your case this means that the compiler sees B::DoSomething. It then tries to match the argument list, which fails.

One solution would be to pull down the overload from A into B's scope:

class B : public A {
public:
    using A::DoSomething;
    // …
}

Solution 2

Overload resolution is one of the ugliest parts of C++

Basically the compiler finds a name match "DoSomething(int)" in the scope of B, sees the parameters don't match, and stops with an error.

It can be overcome by using the A::DoSomething in class B

class A  
{  
  public:  
    int DoSomething() {return 0;}
};  

class B : public A  
{  
  public:  
    using A::DoSomething;
    int DoSomething(int x) {return 1;} 
};   


int main(int argc, char** argv)
{
  B* b = new B();  
  // b->A::DoSomething();    // still works, but...
  b->DoSomething();    // works now too
  delete b;  
  return 0;
}

Solution 3

No, this behaviour is present to ensure that you don't get caught out inheriting from distant base classes by mistake.

To get around it, you need to tell the compiler which method you want to call by placing a using A::DoSomething in the B class.

See this article for a quick and easy overview of this behaviour.

Solution 4

The presence of a method in a derived class hides all methods with the same name (regardless of parameters) in base classes. This is done to avoid problems like this:

class A {} ;
class B :public A
{
    void DoSomething(long) {...}
}

B b;
b.DoSomething(1);     // calls B::DoSomething((long)1));

than later someone changes class A:

class A
{
    void DoSomething(int ) {...}
}

now suddenly:

B b;
b.DoSomething(1);     // calls A::DoSomething(1);

In other words, if it didn't work like this, a unrelated change in a class you don't control (A), could silently affect how your code works.

Solution 5

When you define a function in a derived class then it hides all the functions with that name in the base class. If the base class function is virtual and has a compatible signature then the derived class function also overrides the base class function. However, that doesn't affect the visibility.

You can make the base class function visible with a using declaration:

class B : public A  
{  
  public:  
    int DoSomething(int x) {return 1;};  
    using A::DoSomething;
};  
Share:
12,406
Admin
Author by

Admin

Updated on June 01, 2022

Comments

  • Admin
    Admin almost 2 years

    Given the following example, why do I have to explicitly use the statement b->A::DoSomething() rather than just b->DoSomething()?

    Shouldn't the compiler's overload resolution figure out which method I'm talking about?

    I'm using Microsoft VS 2005. (Note: using virtual doesn't help in this case.)

    class A
    {
      public:
        int DoSomething() {return 0;};
    };
    
    class B : public A
    {
      public:
        int DoSomething(int x) {return 1;};
    };
    
    int main()
    {
      B* b = new B();
      b->A::DoSomething();    //Why this?
      //b->DoSomething();    //Why not this? (Gives compiler error.)
      delete b;
      return 0;
    }
    
  • Chubsdad
    Chubsdad over 13 years
    In fact if they are not in the same scope, they are not called overloads as well
  • Konrad Rudolph
    Konrad Rudolph over 13 years
    @Chubsdad: That’s why I put the word in quotes. And once the method is pulled into the same scope, it becomes an overload.
  • Pravar Jawalekar
    Pravar Jawalekar over 6 years
    Very nice point, I must say. Most answers I have seen talked about why error occurs and how to avoid it but your point shows why this feature is essential and useful in real world scenario!!