C++ 函数重载——两个函数仅因默认参数不同而不同 A类{ 公众: void foo(int x) { cout
不可以,使用单个参数调用函数时会出现歧义C++ 函数重载——两个函数仅因默认参数不同而不同 A类{ 公众: void foo(int x) { cout,c++,overloading,C++,Overloading,不可以,使用单个参数调用函数时会出现歧义 如果您需要这样做,这是一种代码味道。不,您不能基于所传递的参数值重载函数,因此也不允许基于默认参数值重载函数 只能基于以下条件重载函数: 参数类型 参数数 论元序列& 限定符,如const和volatile 当然,编译器是否接受重载取决于以下事实: 如果编译器明确地解析函数的调用 在您的情况下,编译器无法解决歧义,例如:如果您简单地调用函数,编译器将不知道要调用哪个重载函数: class A{ public: void foo
如果您需要这样做,这是一种代码味道。不,您不能基于所传递的参数值重载函数,因此也不允许基于默认参数值重载函数 只能基于以下条件重载函数:
- 参数类型
- 参数数
- 论元序列&
- 限定符,如
和const
volatile
如果编译器明确地解析函数的调用 在您的情况下,编译器无法解决歧义,例如:如果您简单地调用函数,编译器将不知道要调用哪个重载函数:
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?
}
编译器无法做出决定,因此出现错误。为什么不能
foo(100);
A类{
公众:
无效foo(整数x=10,整数y=10)
{
cout我想你不能。因为函数/运算符重载是由编译器在编译时解决的。因此,仅通过提供默认参数来重载函数将导致歧义和编译器错误。想想看——在编译时,编译器必须决定选择哪一个。我不能,除非你同时提供这两个参数。因此mpiler别无选择,只能举手说,用不需要神秘Meg的代码再试一次。我确实不建议这样做,但你可以定义这种模棱两可的方法,并通过不同的接口使用它们。
(以下内容至少适用于使用-std=c++11的GCC4.8.0。)
考虑两个接口:
class A{
public:
void foo(int x=10, int y=10)
{
cout << "foo with two\n";
}
};
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
为不同参数重载了两次funky
方法,即相同的方法名称,但一个方法使用单个int,而另一个方法使用两个int。注意,在接口实现中,funky
方法需要有两个实现(一个用于一个参数,另一个用于两个参数)
IInterface2
有一个funky
方法,调用该方法时可以使用一个或两个int。如果没有显式提供,则默认使用第二个int。注意,在接口实现中,funky
方法只需要一个实现(无论在调用过程中提供了一个还是两个参数,它总是需要两个参数)
实现两个接口的类:
class A{
public:
void foo(int x=10, int y=10)
{
cout << "foo with two\n";
}
};
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;
};
为了便于说明,Foo
还添加了第三个重载版本的funky
方法,该方法包含三个参数(一个强制参数和两个可选参数)
Foo
现在可以如下图所示使用。Foo
,master
的实例可以直接使用,或者不同的客户端可以访问master
对象的不同接口
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); }
};
这将产生以下输出:
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);
总之,类可能具有明显冲突的重载方法版本。调用方法时必须解决模糊性(否则代码将无法编译)
PS:同样,由于上述方法违反了KISS原则,我不会容忍它。这种模糊性不是因为可选参数而产生的,而是只有当你有相同选项但名称不同的同一种原型时才会发生。.这就是我想出来的
当我的例子和你的相似时,我真的觉得我很幸运。但是当我把两个不同的原型名称和相同的可选参数放在一起时,它开始抱怨模棱两可
下面给出了模糊度误差
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)
但这并不重要,请注意,我仍然使用一个可选参数
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)
{
//...
}
如果是foo(10),应该调用哪个函数如果你回答这个问题,你会发现你的解决方案是多余的。为什么你要这么做?你真的有两个不同的函数,可以用相同的参数调用同一个名称,并执行不同的任务吗?如果你需要两个不同的实现,考虑提供不同的名称,其他开发人员会很乐意回复。用名字来描述他们在做什么…@DavidRodríguez dribeas,事实上不是。但我刚刚想到了这一点,:-)所以,我不能用另一个函数重载一个与第一个函数不同的函数,只是一个默认参数?@Alcott:不,你不能,编译器将如何决定调用哪个函数?编译器无法确定唯一的区别是否是默认参数。有趣的是,你的第二段与你的第一段相矛盾,因为争论的次数不同。@LuchianGrigore:是的,很有趣,好吧。看起来你玩得很开心。是的,但因为今天是星期五,所以这总是件好事。