在C ++中放置默认参数值的位置?

默认参数值的地方是什么? 只是在函数定义,或声明,或两个地方?

默认参数值必须出现在声明中,因为这是调用者看到的唯一的东西。

编辑:正如其他人指出的,你可以有定义的论点,但我会build议编写所有的代码,如果这是不正确的。

你可以做,但从来都不是。 通常你在函数声明中做,然后所有的调用者都可以使用这个默认值。 但是, 您可以在函数定义中做到这一点,然后只有那些看到定义的人才能够使用默认值。

在声明(.h)中最有用的地方是所有的用户都会看到它。

有些人喜欢在实现中添加默认值(作为注释):

void foo(int x = 42, int y = 21); void foo(int x /* = 42 */, int y /* = 21 */) { ... } 

但是,这意味着重复,并且会增加注释与代码不同步的可能性(比注释错误的注释更糟糕的是未注释的代码?)。

虽然这是一个“旧”的线程,我仍然想要添加以下内容:

我遇到了下一个案例:

  • 在一个类的头文件中,我有
 int SetI2cSlaveAddress( UCHAR addr, bool force ); 
  • 在这个类的源文件中,我有
 int CI2cHal::SetI2cSlaveAddress( UCHAR addr, bool force = false ) { ... } 

正如我们所看到的,我已经把参数“force”的默认值放在类源文件中,而不是在类头文件中。

然后,我在派生类中使用该函数(派生类以公共方式inheritance基类):

SetI2cSlaveAddress( addr );

假设它将“force”参数视为“假”“理所当然”。

然而,编译器( 放在C + + 11模式 )抱怨,给了我下面的编译器错误:

 /home/.../mystuff/domoproject/lib/i2cdevs/max6956io.cpp: In member function 'void CMax6956Io::Init(unsigned char, unsigned char, unsigned int)': /home/.../mystuff/domoproject/lib/i2cdevs/max6956io.cpp:26:30: error: no matching function for call to 'CMax6956Io::SetI2cSlaveAddress(unsigned char&)' /home/.../mystuff/domoproject/lib/i2cdevs/max6956io.cpp:26:30: note: candidate is: In file included from /home/geertvc/mystuff/domoproject/lib/i2cdevs/../../include/i2cdevs/max6956io.h:35:0, from /home/geertvc/mystuff/domoproject/lib/i2cdevs/max6956io.cpp:1: /home/.../mystuff/domoproject/lib/i2cdevs/../../include/i2chal/i2chal.h:65:9: note: int CI2cHal::SetI2cSlaveAddress(unsigned char, bool) /home/.../mystuff/domoproject/lib/i2cdevs/../../include/i2chal/i2chal.h:65:9: note: candidate expects 2 arguments, 1 provided make[2]: *** [lib/i2cdevs/CMakeFiles/i2cdevs.dir/max6956io.cpp.o] Error 1 make[1]: *** [lib/i2cdevs/CMakeFiles/i2cdevs.dir/all] Error 2 make: *** [all] Error 2 

但是当我在基类的文件中添加默认参数时:

int SetI2cSlaveAddress( UCHAR addr, bool force = false );

并从基类的源文件中删除它:

int CI2cHal::SetI2cSlaveAddress( UCHAR addr, bool force )

那么编译器很高兴,所有代码都按预期工作(我可以给函数SetI2cSlaveAddress()提供一个或两个参数)!

所以,不仅对于一个类的用户来说,把一个参数的默认值放在头文件中是非常重要的,而且对于编译和function上的明智看来似乎是必须的!

如果这些函数是暴露的 – 非成员,公共或保护 – 则调用者应该知道它们,并且默认值必须在标题中。

如果这些函数是私有的,而且是非线性的,那么将默认值放在实现文件中是有意义的,因为这允许不会触发客户端重新编译的更改(对于在企业级中共享的低级库发展)。 也就是说,这肯定会让人感到困惑,并且在头文件中以更直观的方式呈现API时有文档价值,所以select妥协 – 尽pipe在没有任何令人信服的理由的情况下一致性是主要的。

声明通常是最“有用的”,但这取决于你想如何使用这个类。

两者都是无效的。

好问题…我发现编程人员通常使用声明来声明默认值。 我一直以一种方式(或警告)或另一种方式基于编译器

 void testFunct(int nVal1, int nVal2=500); void testFunct(int nVal1, int nVal2) { using namespace std; cout << nVal1 << << nVal2 << endl; } 

还有一点我没有find任何人提到:

如果你有虚拟方法,每个声明都可以有自己的默认值!

这取决于您所调用的接口将使用哪个值。

关于ideone的例子

 struct iface { virtual void test(int a = 0) { std::cout << a; } }; struct impl : public iface { virtual void test(int a = 5) override { std::cout << a; } }; int main() { impl d; d.test(); iface* a = &d; a->test(); } 

它打印50

我强烈劝阻你这样使用它

你可以按照标准来做,但是要记住,如果你的代码在包含默认参数的定义之前看到没有默认参数的声明,那么就会出现编译错误。

例如,如果包含包含函数声明而没有默认参数列表的头文件,编译器会查找该原型文件,因为它不知道默认参数值,因此原型不匹配。

如果你在定义中使用默认参数的函数,那么包含该文件,但我不会build议。

再加一点。 具有默认参数的函数声明应该从右到左从上到下 sorting

例如 ,在下面的函数声明中,如果您更改声明顺序,那么编译器会给您一个缺less的默认参数错误。 原因是编译器允许你在同一个作用域内把函数声明和默认参数分开,但是它应该是从RIGHT到LEFT(默认参数)和从TOP到BOTTOM(函数声明默认参数的顺序)的顺序。

 //declaration void function(char const *msg, bool three, bool two, bool one = false); void function(char const *msg, bool three = true, bool two, bool one); // Error void function(char const *msg, bool three, bool two = true, bool one); // OK //void function(char const *msg, bool three = true, bool two, bool one); // OK int main() { function("Using only one Default Argument", false, true); function("Using Two Default Arguments", false); function("Using Three Default Arguments"); return 0; } //definition void function(char const *msg, bool three, bool two, bool one ) { std::cout<<msg<<" "<<three<<" "<<two<<" "<<one<<std::endl; }