Alcott
Alcott

Reputation: 18575

Function overloading -- two functions only differ by a 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?

Upvotes: 6

Views: 17245

Answers (7)

Todd Murray
Todd Murray

Reputation: 423

Why not?

class A{
    public:

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

Upvotes: 2

SSpoke
SSpoke

Reputation: 5836

The ambiguity doesn't happen because of optional parameters but only happens when you have the same kind of prototype with same optionals but different names.. thats what I figured out..

I actually thought i got lucky when my example similar to yours worked.. but when I put 2 different prototype names with same optional parameters then it started complaining about ambiguities

This below gives the ambiguity error

void UpdateTextColor(HWND hwndControl, DWORD text_color, DWORD back_color, BOOL control_back_color);
void CreateColoredText(HWND hwndControl, DWORD text_color, DWORD back_color, BOOL control_back_color);

void UpdateTextColor(HWND hwndControl, DWORD text_color, DWORD back_color, BOOL control_back_color = FALSE)
{
   //...
}

void CreateColoredText(HWND hwndControl, DWORD text_color, DWORD back_color, BOOL control_back_color = FALSE)
{
   //...
}

But this doesn't and note I am still using a optional parameter

void UpdateTextColor(HWND hwndControl, DWORD text_color, DWORD back_color);
void CreateColoredText(HWND hwndControl, DWORD text_color, DWORD back_color, BOOL control_back_color);

void UpdateTextColor(HWND hwndControl, DWORD text_color, DWORD back_color)
{
   //...
}

void CreateColoredText(HWND hwndControl, DWORD text_color, DWORD back_color, BOOL control_back_color = FALSE)
{
   //...
}

//My call is like this (note only 3 params used out of 4)

CreateColoredText(GetDlgItem(hDlg, BLAHBLAH), RGB(0, 0, 0), RGB(127, 127, 127));

Upvotes: 0

Petr Vepřek
Petr Vepřek

Reputation: 1648

I do NOT recommend this but you CAN define such ambiguous methods and use them through 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 funky method overloaded twice for different arguments i.e. same method name but one takes single int while another takes two ints. Note in interface implementation, funky method will need to have two implementations (one for one argument and another for two arguments).

IInterface2 has single funky method that takes either one or two ints when invoked. If not provided explicitly, the second int is defaulted. Note in interface implementation, funky method will need to have only one implementation (and it always takes two arguments regardless of whether one or two were provided during invocation).

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 third overloaded version of funky method, one that takes three arguments (one mandatory and two optional).

Foo can now be used as illustrated below. Instance of Foo, master, can be used either directly, or different clients can get access to different interfaces of master object.

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 produce 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)

In summary, class can have apparently conflicting overloaded versions of a method. Ambiguity MUST be resolved when the method is invoked (or else the code will not compile).

PS: Again, since the above approach breaks the KISS principle, I do not condone it.

Upvotes: 2

Ed Heal
Ed Heal

Reputation: 59987

Think about it - at compile time the compiler has to decide what one to chose. I cannot unless you supply both parameters. So the compiler has no choice but to throw its hands up and say that try again with code that does not require Mystic Meg.

Upvotes: 1

Alok Save
Alok Save

Reputation: 206508

No you cannot overload functions on basis of value of the argument being passed, So overloading on the basis of value of default argument is not allowed either.

You can only overload functions only on the basis of:

  • Type of arguments
  • Number of arguments
  • Sequence of arguments &
  • Qualifiers like const and volatile.

Ofcourse, Whether the overload is accepted by the compiler depends on the fact:
If the compiler resolve calling of the function unambiguously.

In your case, the compiler cannot resolve the ambiguity, for ex: The compiler wouldn't know which overloaded function to call if you simple called the function as:

 foo(100);

The compiler cannot make the decision and hence the error.

Upvotes: 7

Apoorva sahay
Apoorva sahay

Reputation: 1930

I think you can't. Because function/operator overloading is resolved by compiler at compile time. So overloading a function just by providing a default argument will cause ambiguity and compiler error.

Upvotes: 0

Luchian Grigore
Luchian Grigore

Reputation: 258548

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

And if you need to do this, it's a code smell.

Upvotes: 3

Related Questions