函数类型不同是不行的,但是你需要知道什么是函数类型的一部分,什么不是。在您的情况下,const
for 参数并不重要,因此函数类型是相同的,尽管声明看起来与定义不同。
在你的情况下
8.3.5 函数[dcl.fct]
5一个名称可用于单个范围内的多个不同功能;这是函数重载(第 13 条)。函数的所有声明都应在返回类型和参数类型列表中完全一致。使用以下规则确定函数的类型。每个参数的类型(包括函数参数包)由其自己的 decl-specifier-seq 和声明符确定。在确定每个参数的类型后,将“T的数组”或“返回T的函数”类型的任何参数分别调整为“指向T的指针”或“返回T的函数的指针”。在生成参数类型列表后,任何修改参数类型的顶级 cv 限定符都会在形成函数类型时被删除。转换后的参数类型的结果列表以及省略号或函数参数包的存在与否是函数的参数类型列表。[ 注意:此转换不影响参数的类型。例如,int(*)(const int p, decltype(p)*)
并且int(*)(int, const int*)
是相同的类型。——尾注]
看起来,它需要一些解释,所以我们开始吧: 在我们的例子中,重要的一句话是:在生成参数类型列表之后,在形成函数类型时,任何修改参数类型的顶级 cv 限定符都将被删除。
这意味着所有顶级cv 限定符都被删除。为了解释顶级的含义,我将以非法的方式编写类型来强调 aconst
所指的内容:
const int
= (const (int))
-> 这是顶级的const
const int*
= ((const (int))*)
-> 不是顶级,是二级
const int* const
= (((const (int))*) const)
-> 第二个const
在顶层
const int&
= ((const (int))&)
-> 不是顶级的
我希望这能消除对函数类型的一些误解。
对于您的其他问题:我建议保持声明和定义相同,因为它可能会使人们感到困惑(就像这个问题所证明的那样;)。
对于main
您给出的示例:
int main( const int argc, const char* const argv[] )
是,根据标准的上述引用,相当于:
int main( int argc, const char* const* argv )
因此添加const
的 forargv
最终不会作为顶层const
被删除,因此它是一个格式错误的函数类型 for main
,它期望:
int main( int argc, char** argv )
关于省略参数名称的最后一个问题:我不会这样做,因为对我来说,它们是函数文档的一部分。它们传达函数的意图和语义(如果您明智地选择它们)。