声明为consts的函数args在定义时变为非常量

Sit*_*esh 5 c++ constants c++11 c++14

class A
{
 public:
    void f(const int i);
};
void A::f(int i)
{
    std::cout<<++i<<std::endl;
}
int main()
{
   A a;
   a.f(1);
}
Run Code Online (Sandbox Code Playgroud)

为什么编译器在这种情况下不会出错?为什么定义会覆盖常量参数?此外,当参数是类型时reference (&),编译器会抛出错误,但为什么不在这种情况下呢?

是否有任何编译器标志可以在这些提到的情况下启用警告?

我对编译器错误POV感兴趣.因为可以很容易地将声明(const)和定义(非常量)放在一起,但编译器仍然接受它.如果可以犯错误,最终会犯错误.当存在这样的差异时,为什么编译器不能抱怨.

Edg*_*jān 5

11.3.5函数[dcl.fct]:

  1. 单个名称可用于单个范围内的多个不同功能; 这是函数重载(第16条).函数的所有声明都应在返回类型和参数类型列表中完全一致.使用以下规则确定函数的类型.每个参数的类型(包括函数参数包)由其自己的decl-specifier-seq和声明符确定.在确定每个参数的类型之后,将"T数组"或函数类型T的任何参数调整为"指向T的指针".生成参数类型列表后,在形成函数类型时,将删除修改参数类型的任何 顶级cv限定符.生成的已转换参数类型列表以及省略号或函数参数包的存在与否是函数的parameter-type-list.

基本上,它意味着,const int并且int在您的问题的背景下可以互换.

另一方面,如果你添加一个引用,就像const int&,const不再是顶级cv-qualifier(它将引用的值标记为const),所以编译器会抱怨.

通常,const添加到定义中以强调参数在函数体内没有改变.


R S*_*ahu 3

函数声明

void f(const T arg);
Run Code Online (Sandbox Code Playgroud)

void f(T arg);
Run Code Online (Sandbox Code Playgroud)

然而,

void f(const T& arg);
Run Code Online (Sandbox Code Playgroud)

不等于

void f(T& arg);
Run Code Online (Sandbox Code Playgroud)

void f(const T* arg);
Run Code Online (Sandbox Code Playgroud)

不等于

void f(T* arg);
Run Code Online (Sandbox Code Playgroud)
void f(const T arg);
void f(T arg);
Run Code Online (Sandbox Code Playgroud)

是相同的,因为出于函数解析的目的,顶级 cv 限定符被删除。在那里,const-ness 应用于顶级类型T

奥托,

void f(const T& arg);
void f(T& arg);
Run Code Online (Sandbox Code Playgroud)

不一样,因为const-ness 应用于引用所引用的对象arg,而不是应用于arg它本身,这只是一个顶级的东西。

  • 提及*顶级*常量来解释它。C++ 中并非所有常量都相同。 (2认同)
  • @Stargateur:只要“T”是值类型,它在这种情况下就“是”相同的。`const` 告诉*调用者*他的参数不会被 `f()` 改变。由于参数无论如何都是按值传递的,因此即使对于值类型,“f( T arg )”声明也遵守“f( const T arg )”声明所指示的约定。检查埃德加的答案(或链接的欺骗)以获取标准法律术语。 (2认同)