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:是的,很有趣,好吧。看起来你玩得很开心。是的,但因为今天是星期五,所以这总是件好事。