Mar*_*tos 296
默认参数值必须出现在声明中,因为这是调用者看到的唯一内容.
编辑:正如其他人指出的那样,你可以在定义上有参数,但我建议把所有代码都写成不正确.
sha*_*oth 94
你可以做任何一种,但绝不能同时做到.通常在函数声明中执行它,然后所有调用者都可以使用该默认值.但是,您可以在函数定义中执行此操作,然后只有那些看到定义的人才能使用默认值.
650*_*502 80
最有用的地方是声明(.h),以便所有用户都能看到它.
有些人喜欢在实现中添加默认值(作为注释):
void foo(int x = 42,
int y = 21);
void foo(int x /* = 42 */,
int y /* = 21 */)
{
...
}
Run Code Online (Sandbox Code Playgroud)
但是,这意味着重复,并且会增加注释与代码不同步的可能性(什么比未注释的代码更糟糕?带有误导性注释的代码!).
Gee*_*tVc 38
虽然这是一个"旧"线程,但我还是想添加以下内容:
我经历了下一个案例:
Run Code Online (Sandbox Code Playgroud)int SetI2cSlaveAddress( UCHAR addr, bool force );
Run Code Online (Sandbox Code Playgroud)int CI2cHal::SetI2cSlaveAddress( UCHAR addr, bool force = false ) { ... }
可以看出,我已将参数"force"的默认值放在类源文件中,而不是在类头文件中.
然后我在派生类中使用该函数如下(派生类以公共方式继承基类):
SetI2cSlaveAddress( addr );
假设它将"force"参数视为"false"'被授予'.
但是,编译器(放入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
Run Code Online (Sandbox Code Playgroud)
但是当我在基类的头文件中添加默认参数时:
int SetI2cSlaveAddress( UCHAR addr, bool force = false );
并从基类的源文件中删除它:
int CI2cHal::SetI2cSlaveAddress( UCHAR addr, bool force )
然后编译器很开心,所有代码都按预期工作(我可以给函数提供一个或两个参数SetI2cSlaveAddress())!
因此,不仅对于类的用户而言,将参数的默认值放在头文件中也很重要,同时编译和功能明智,这显然是必须的!
Ton*_*roy 13
如果函数是公开的 - 非成员,公共或受保护 - 那么调用者应该知道它们,并且默认值必须在标题中.
如果函数是私有的并且是异地的,那么将默认值放在实现文件中是有意义的,因为这允许更改不会触发客户端重新编译(对于企业级共享的低级库,这有时是一个严重的问题)发展).也就是说,它肯定会让人感到困惑,并且在标题中以更直观的方式呈现API有文档价值,所以选择你的妥协 - 尽管一致性是主要的,当没有任何令人信服的理由时.
ice*_*911 10
好问题......我发现编码员通常使用声明来声明默认值.基于编译器,我一直被一种方式(或警告)或另一种方式所控制
void testFunct(int nVal1, int nVal2=500);
void testFunct(int nVal1, int nVal2)
{
using namespace std;
cout << nVal1 << << nVal2 << endl;
}
Run Code Online (Sandbox Code Playgroud)
rel*_*xxx 10
还有一点我没有发现有人提到:
如果你有虚方法,每个声明都有自己的默认值!
这取决于您调用的接口将使用哪个值.
关于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();
}
Run Code Online (Sandbox Code Playgroud)
它打印 50
我强烈反对你这样使用它