为何`using namespace`会干扰C++函数的默认参数?
问题分析:函数默认参数存在却报参数不足错误
有一个三文件的C++项目,初始代码可正常编译运行,但修改my_class.cpp的命名空间写法后,编译报错:
error C2660: 'baz::doDefault': function does not take 0 arguments
明明头文件中doDefault的声明带有默认参数bool actually = false,却出现这个错误,原因如下:
修改后的my_class.cpp代码
#include "my_class.h" #include <stdio.h> using namespace foo::bar; namespace baz { void doDefault(bool actually /* = false*/) { actually ? printf("true") : printf("false"); } void printDefault() { doDefault(); } } // namespace baz
错误核心原因
问题出在命名空间的作用域混淆上:
- 头文件里的
doDefault属于foo::bar::baz命名空间。 - 修改后的代码中,
using namespace foo::bar;只是让当前代码可以直接引用foo::bar下的成员,但直接写namespace baz并不是扩展foo::bar::baz,而是在全局命名空间下新建了一个完全独立的baz命名空间。 - 这个全局
baz里的doDefault函数,没有有效默认参数(默认参数必须在头文件的声明处指定,定义处的注释或重复写法会被编译器忽略),而且它和头文件里的foo::bar::baz::doDefault是两个完全无关的函数。 - 当
printDefault中调用doDefault()时,实际调用的是全局baz::doDefault,这个函数要求必须传入一个bool参数,因此触发参数不足的编译错误。
解决办法
要正确扩展foo::bar::baz命名空间,有两种可行写法:
写法1:嵌套命名空间(与初始代码一致)
#include "my_class.h" #include <stdio.h> namespace foo::bar { namespace baz { void doDefault(bool actually) { actually ? printf("true") : printf("false"); } void printDefault() { doDefault(); } } // namespace baz } // namespace foo::bar
写法2:直接指定完整命名空间
#include "my_class.h" #include <stdio.h> namespace foo::bar::baz { void doDefault(bool actually) { actually ? printf("true") : printf("false"); } void printDefault() { doDefault(); } } // namespace foo::bar::baz
注意:函数的默认参数只需在头文件的声明中定义,函数定义处不需要重复编写(即使写了也不会生效)。
内容的提问来源于stack exchange,提问作者Tare
相关产品推荐
相关产品推荐

