21

我对 C++ 还比较陌生,我似乎无法弄清楚以下两种编码可能采用一个参数或两个或三个或更多参数的函数的方式的区别。无论如何,这是我的观点

函数重载:

int aClass::doSomething(int required)
{
    //DO SOMETHING
}

int aClass::doSomething(int required, int optional)
{
    //DO SOMETHING
}

这与默认值有何不同:

int aClass::doSomething(int required, int optional = 0)
{
    //DO SOMETHING
}

我知道在不同的情况下,一个可能比另一个更合适,但是在这些选项之间进行选择时我应该注意哪些事项?

4

4 回答 4

27

有几个技术原因更喜欢重载而不是默认参数,它们在 Google 的C++ 样式指南默认参数部分中有很好的阐述:

在存在默认参数的情况下,函数指针会令人困惑,因为函数签名通常与调用签名不匹配。向现有函数添加默认参数会更改其类型,这可能会导致代码获取其地址时出现问题。添加函数重载可以避免这些问题。

和:

默认参数可能会导致代码变得更庞大,因为它们在每个调用点都被复制 - 与重载函数相反,其中“默认”仅出现在函数定义中。

从积极的方面来说,它说:

通常你有一个使用默认值的函数,但有时你想覆盖默认值。默认参数允许一种简单的方法来执行此操作,而无需为罕见的异常定义许多函数。

因此,您的选择将取决于负面问题与您的应用程序的相关程度。

于 2014-06-11T19:42:08.950 回答
6

首先,您说的是重载,而不是覆盖。virtual对派生类中的函数进行覆盖。重载是指相同的函数名称具有不同的签名。

区别是合乎逻辑的 - 在第一种情况(2 个版本)中,两个函数的行为可能完全不同,而第二种情况将具有或多或少相同的逻辑。这真的取决于你。

于 2013-04-08T10:19:25.070 回答
4

编译器并不关心您使用其中的哪一个。想象一下,你把它写成两个构造函数,它们最终有大约 20 行长。进一步想象有 19 行是相同的,不同的行读取

foo = 0;

在一个版本中和

foo = optional;

在另一个。在这种情况下,使用可选参数会使您的代码更具可读性和可理解性。在另一种没有可选参数的语言中,您可以通过让单参数版本调用双参数版本并将零作为第二个参数传递给它来实现这一点。

现在想象一对不同的构造函数或函数,它们也有大约 20 行长但完全不同。例如,第二个参数是一个 ID,如果提供,则在数据库中查找内容,如果不是,则将值设置为nullptr0 等。你可以有一个默认值(-1 很受欢迎)但是函数的主体将充满

if (ID == -1)
{
    foo = 0;
}
else 
{
    foo = DbLookup(ID);
}

这可能很难阅读,并且会使单个函数比两个单独的函数长得多。我见过一个巨人if的函数,它本质上将整个事情分成两个单独的块,没有共同的代码,我已经看到随着计算的进行,相同的条件测试了 4 或 5 次。两者都很难阅读。

这就是关于 C++ 的事情。有很多方法可以完成大多数事情。但是这些不同的方式服务于不同的目的,一旦你“得到”了细微的差异,你就会写出更好的代码。在这种情况下,“更好”意味着更短、更快(所有这些if成本执行时间)和更具表现力 - 阅读它的人可以快速理解您的意图。

于 2013-04-08T10:29:02.353 回答
2

constructor如果您提供了几个s ,则您正在使用重载功能。这种情况下的优点是,您可以对每个constructor传递的参数做出不同的反应。如果这很重要,请使用重载。
如果您可以为default参数提供合适的值并且这些值不会影响代码的正常运行,请使用默认参数。

有关 SO 的线程,请参见此处

于 2013-04-08T10:19:18.317 回答