Eri*_*tný 8 c c++ arguments extern
从这里看来,C不支持默认参数.
我在导出的库中有以下方法:
extern "C"
{
__declspec (dllexport) uintptr_t Method(int freq, int *pRetval, bool *support2MHz);
}
Run Code Online (Sandbox Code Playgroud)
如果我使最后一个参数可选像这样:
extern "C"
{
__declspec (dllexport) uintptr_t Method(int freq, int *pRetval, bool *support2MHz = NULL);
}
Run Code Online (Sandbox Code Playgroud)
我的dll仍在编译中.我的问题是为什么?每个人都说C代码不支持默认参数.
我使用C++ for MS 2015.
正如molbdnilo在评论中已经注意到的那样,extern "C"并不意味着"这是C代码",而是"这是带有C链接的代码" - 即不会执行此函数的名称修改,因此您可以从C调用它"预期"函数调用语法.C++编译器破坏了函数的名称,因此它们可以支持函数重载,因为同一函数的不同重载的符号名称必须是唯一的(基本上,它们使用函数的作用域,名称和参数类型来创建唯一的符号名称).
根据[dcl.fct.default],该标准第1和第2段:
如果在参数声明中指定了initializer子句,则此 initializer子句将用作默认参数.默认参数将用于缺少尾随参数的调用中.
[例子:声明
Run Code Online (Sandbox Code Playgroud)void point(int = 3, int = 4);声明一个可以使用零个,一个或两个类型参数调用的函数
int.它可以通过以下任何方式调用:Run Code Online (Sandbox Code Playgroud)point(1,2); point(1); point();最后两个调用分别等同于
point(1,4)和point(3,4). - 结束例子]
此外,第9段规定:
默认参数不是函数类型的一部分.[例如:
Run Code Online (Sandbox Code Playgroud)int f(int = 0); void h() { int j = f(1); int k = f(); // OK, means f(0) } int (*p1)(int) = &f; int (*p2)() = &f; // error: type mismatch- 结束例子]
因此,对于具有默认参数的函数int foo(int x, int y = 0),编译器不会生成两个重载(int foo(int x, int y)和int foo(int x),具有y固定到0),而是替换的形式的每一个电话foo(x)与一个呼叫foo(x, 0).在你的具体例子中,extern "C"这意味着编译器只生成一个带有C链接的符号,Method因此没有名称冲突.
您可以在godbolt的实例中看到各种编译器的这种行为.
但是,正如Afshin在评论中已经提到的那样,实现它的方式使得无法将默认参数"传播"到共享库的其他用户,所以如果你想从C中使用它,你仍然需要通过所有函数的参数.