Function overloading - two functions differ only in the default parameter

class A{
    public:
        void foo(int x)
        {
            cout << "foo with one\n";
        }

        void foo(int x, int y=10)
        {
            cout << "foo with two\n";
        }
};

int main()
{
    A a;
    a.foo(1);   //error?
}

      

So why can't I overload void foo(int)

with a function that takes a default parameter?

+3


source to share


6 answers


No, you cannot overload functions based on the value of the passed argument, so overloading based on the default argument value is also not allowed.

You can only overload functions based on only:

  • Argument type
  • Number of arguments
  • Argument Sequence &
  • Qualifiers such as const

    and volatile

    .

Of course, whether the overloading will be accepted by the compiler depends on the fact:
If the compiler allows the function call unambiguously.



In your case, the compiler cannot resolve the ambiguity, for example: The compiler didn't know which overloaded function to call if you just called the function like:

 foo(100);

      

The compiler cannot make a decision and hence an error.

+4


source


No, you can't, there will be ambiguity when calling a function with one parameter.



And if you have to do that, it's a code smell.

+2


source


Why not?

class A{
public:

    void foo(int x=10, int y=10)
    {
        cout << "foo with two\n";
    }

      

};

+2


source


I recommend this NOT , but you CAN define such ambiguous methods and use them across different interfaces. (The following works at least with gcc 4.8.0 using -std = C ++ 11.)

Consider two interfaces:

class IInterface1
{
public:
   virtual void funky(int i) = 0;
   virtual void funky(int i, int j) = 0;
};

class IInterface2
{
public:
   virtual void funky(int i, int j = 0) = 0;
};

      

IInterface1

has a method funky

overloaded twice for different arguments. Same method name, but one takes one int and the other takes two int. Note that in an interface implementation, a method funky

must have two implementations (one for one argument and the other for two arguments).

IInterface2

has a single method funky

that takes one or two int values ​​when called. Unless explicitly specified, the second int is the default. Note that in the implementation of the interface, a method funky

must only have one (and it always takes two arguments, regardless of whether one or two were supplied at the time of the call).

A class that implements both interfaces:

class Foo : public IInterface1, public IInterface2
{
public:
   void funky(int i) override
      { printf("  funky(int i) -> funky(%d)\n", i); }
   void funky(int i, int j = 0) override
      { printf("  funky(int i, int j = 0) -> funky(%d, %d)\n", i, j); }
   void funky(int i, int j = 0, int k = 0)
      { printf("  funky(int i, int j = 0, int k = 0) -> funky(%d, %d, %d)\n", i, j, k); }
};

      

For illustration, Foo

also adds a third overloaded version of the method funky

, which takes three arguments (one required and two optional).

Foo

can now be used as shown below. An instance Foo

, master

can be used either directly or different clients can access the different interfaces of the object master

.

Foo master;
IInterface1& client1 = master;
IInterface2& client2 = master;

// AMBIGUOUS: master.funky(1); 
// AMBIGUOUS: master.funky(2,3);
puts("master.funky(4, 5, 6);");
master.funky(4, 5, 6);

puts("client1.funky(7);");
client1.funky(7);
puts("client1.funky(8, 9);");
client1.funky(8, 9);

puts("client2.funky(10);");
client2.funky(10);
puts("client2.funky(11, 12);");
client2.funky(11, 12);

      

This will lead to the following output:

master.funky(4, 5, 6);
  funky(int i, int j = 0, int k = 0) -> funky(4, 5, 6)
client1.funky(7);
  funky(int i) -> funky(7)
client1.funky(8, 9);
  funky(int i, int j = 0) -> funky(8, 9)
client2.funky(10);
  funky(int i, int j = 0) -> funky(10, 0)
client2.funky(11, 12);
  funky(int i, int j = 0) -> funky(11, 12)

      

Thus, a class can have clearly conflicting method overloads. The ambiguity MUST be resolved when the method is called (otherwise the code will not compile).

PS: Again, since the above approach violates the KISS principle, I disagree with that.

+1


source


I think you cannot. Because function / operator overloading is resolved by the compiler at compile time. Therefore, overloading a function by only providing a default argument will cause an ambiguity and compiler error.

0


source


Think about it - at compile time, the compiler has to decide which to choose. I cannot if you do not specify both parameters. Thus, the compiler has no choice but to raise its hands and say that we will try again with code that does not require Mystic Meg.

0


source







All Articles