具有默认参数的C ++函数的多个声明

时间:2011-07-15 14:38:46

标签: c++ c++11

我几乎所有东西都使用typedef,包括函数。在过去的几周里,我一直在调整我们的C ++代码,以尽可能完全符合ISO C ++ 11标准,使用最终草案文档(N3242)作为指南。

正如我们所知,偶尔会有多个声明通过出现在多个文件中的externs或者重复的typedef进入我们的代码。根据上述doco的第7.1.3节,第145页的摘录,这应该是无害的:

  

3。在给定的非类作用域中,可以使用typedef说明符重新定义该作用域中声明的任何类型的名称,以引用它已引用的类型。

     

[例如:

   typedef struct s { /* ... */ } s; 
   typedef int I; 
   typedef int I; 
   typedef I I;
     

- 结束示例]

所以,我写了一个程序来测试这个。最简单的形式:

typedef int (fcntype)(int, int);
extern fcntype fcn1;

int fcn1(int x, int y) { return x + y; }

int main(int argc, char ** argv) { return fcn1(2, 3); }

使用gcc编译

 -Wfatal-errors -Wswitch-default -Wswitch-enum -Wunused-parameter -Wfloat-equal -Wundef -c -Wstrict-null-sentinel -std=c++0x -pedantic -Wall -Wextra

当然没有问题。让我们复制函数decl:

typedef int (fcntype)(int, int);
extern fcntype fcn1;
extern fcntype fcn1; // woops. probably from an #include ...

int fcn1(int x, int y) { return x + y; }

int main(int argc, char ** argv) { return fcn1(2, 3); }

正如标准预测的那样,没有问题。让我们对原作做出不同的改变:

typedef int (fcntype)(int, int=0); // default param.
extern fcntype fcn1;

int fcn1(int x, int y) { return x + y; }

int main(int argc, char ** argv) { return fcn1(2); } // use the default param

再次,没有问题。当我们同时具有重复的decl和默认参数时会出现问题:

typedef int (fcntype)(int, int=0); // default param.
extern fcntype fcn1;
extern fcntype fcn1; // FYI this is line 3 in the error message below.

int fcn1(int x, int y) { return x + y; }

int main(int argc, char ** argv) { return fcn1(2); } // use the default param

gcc抱怨

decltest.cpp:3: error: default argument given for parameter 2 of ‘int fcn1(int, int)’

当然,我正在按照应该清理的方式清理代码,也就是说我将decls集中到一个更好组织的文件中。但这是编译器中的错误还是对我的默认参数“是”的误解?

3 个答案:

答案 0 :(得分:6)

首先,对于具有相同类型的相同函数声明,最多只能有一个定义默认参数的声明。这是由于§8.3.6[dcl.fct.default] / 4:

  

...默认参数不能由后来的声明重新定义(甚至不是相同的值)。 [示例

...
void m() {
    void f(int, int);     // has no defaults
    f(4);                 // error: wrong number of arguments
    void f(int, int = 5); // OK
    f(4);                 // OK, calls f(4, 5);
    void f(int, int = 5); // error: cannot redefine, even to same value
}
...
     

- 结束示例] ...

另外,正如@Sven注意到的那样,默认参数不会出现在typedef中,尽管即使使用-pedantic g ++也无法捕获它。我认为clangVisual C++拒绝这一点,但我没有尝试过。

答案 1 :(得分:1)

您的标准报价不适用于此处,因为您没有多次声明typedef,而是多次使用它。

默认参数确实是一个棘手的情况,它们只能出现在一个声明中(并且记住,定义本身算作一个声明,即使将默认参数放在前向声明和定义中都是错误的。)

答案 2 :(得分:0)

这会产生相同的错误:

extern int fcn1(int, int=0);
extern int fcn1(int, int=0);

因此,typedef版本不起作用并不奇怪。