从Here开始,C似乎不支持默认参数。
我在导出的库中有以下方法:
extern "C"
{
__declspec (dllexport) uintptr_t Method(int freq, int *pRetval, bool *support2MHz);
}
如果我将最后一个参数设为可选,请执行以下操作:
extern "C"
{
__declspec (dllexport) uintptr_t Method(int freq, int *pRetval, bool *support2MHz = NULL);
}
我的dll仍在编译中。 我的问题是为什么?每个人都说C代码不支持默认参数。
我使用C ++ for MS 2015。
答案 0 :(得分:7)
正如molbdnilo已在评论中指出,extern "C"
并不意味着“这是C代码”,而是“这是带有C链接的代码” - 即不会执行此功能的名称修改,因此您将能够使用“预期”函数调用语法从C调用它。 C ++编译器破坏了函数的名称,因此它们可以支持函数重载,因为同一函数的不同重载的符号名称必须是唯一的(基本上,它们使用函数的作用域,名称和参数类型来创建唯一的符号名称)。 p>
根据[dcl.fct.default],标准第1和第2段:
如果在参数声明中指定了 initializer-clause initializer-clause 用作默认参数。默认参数 将在缺少尾随参数的调用中使用。
[例如:声明
void point(int = 3, int = 4);
声明一个可以使用零个,一个或两个类型参数调用的函数
int
。它可以通过以下任何方式调用:point(1,2); point(1); point();
最后两次调用相当于
point(1,4)
和 分别为point(3,4)
。 - 结束例子]
此外,第9段规定:
默认参数不是函数类型的一部分。 [实施例:
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"
的具体示例中,这意味着编译器仅为Method
生成一个带有C链接的符号,因此没有名称冲突。
您可以在live example on godbolt中看到各种编译器的此行为。
但是,正如Afshin在评论中已经提到的那样,实现它的方式使得无法将默认参数“传播”到共享库的其他用户,所以如果你想从C中使用它,你仍然需要将所有参数传递给函数。