class A{
public:
void foo(int x)
{
cout << \"foo with one\\n\";
}
void foo(int x, int y=10)
{
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:
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.
Why not?
class A{
public:
void foo(int x=10, int y=10)
{
cout << "foo with two\n";
}
};
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.
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));
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.
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.