在const和volatile上重载 - 为什么它通过引用工作?

use*_*112 5 c++ overloading const volatile

我有代码:

#include "stdafx.h"
#include <iostream>

using namespace std;


void func(const int& a)
{
    std::cout << "func(const)" << std::endl;
}

void func(volatile int& a)
{
    std::cout << "func(volatile)" << std::endl;
}

void func(const volatile int& a)
{
    std::cout << "func(const volatile)" << std::endl;
}

int main()
{
    const int a = 0;
    const volatile int b = 0;
    volatile int c = 0;
    func(a);
    func(b);
    func(c);
    system("pause");
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

上面的代码显示了基于参数是否为const/volatile的重载.但是,如果我要将参数更改int&int,则代码不再编译,并且我不能基于const/volatile参数类型进行重载.我不明白为什么我们可以基于const和volatile重载,如果int通过引用传递,但不是如果它通过值传递?

编辑我应该强调我理解引用的作用 - 我不明白为什么允许引用别名在const上重载但普通的int不是.

jua*_*nza 13

问题是顶层const和/或volatile在重载分辨率中被忽略.所以

void foo(const int);
Run Code Online (Sandbox Code Playgroud)

与...完全相同

void foo(int);
Run Code Online (Sandbox Code Playgroud)

并且类似地volatile.这是一种语言规则,因为参数是按值传递的,所以它是有意义的.另一方面,引用const/volatile或指针const/volatile具有不同的含义:不允许在它们引用或指向的内容上调用非const/volatile方法.在这里,const volatile不是顶级.

void foo(int& i);       // can modify what i refers to, and this has effects outside of foo.
void foo(const int& i); // cannot modify what i refers to
Run Code Online (Sandbox Code Playgroud)

上面的两个声明具有非常不同的语义,因此语言使它们在重载决策方面有所区别.


sta*_*ism 4

也许从功能上退后一步,只看用例本身是有用的。

首先,我们将定义一个整数和一个常量整数以供我们的示例使用:

int       anInt     = 1;
const int aConstInt = 1;
Run Code Online (Sandbox Code Playgroud)

接下来,我们看看使用这些变量来设置其他整数和常整数的值时会发生什么:

int       a = anInt;     // This works, we can set an int's value
                         //  using an int
int       b = aConstInt; // This works, we can set an int's value
                         //  using a const int
const int c = anInt;     // This works, we can set a const int's value
                         //  using an int
const int d = aConstInt; // This works, we can set a const int's value
                         //  using a const int
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,没有办法根据行为来决定选择哪个函数重载(const int 可以被 int 和 const int 接受,同样 int 可以被 int 和 a 接受)常量整数)。

接下来,我们看看将第一组变量传递给引用时会发生什么:

int& a = anInt;     // This works because we are using a
                    //  non-constant reference to access a
                    //  non-constant variable.
int& b = aConstInt; // This will NOT work because we are
                    //  trying to access a constant
                    //  variable through a non-constant
                    //  reference (i.e. we could
                    //  potentially change a constant
                    //  variable through the non-const
                    //  reference).

const int& c = anInt;     // This works because we are using a
                          //  constant reference (i.e. "I cannot
                          //  try to change the referenced
                          //  variable using this reference") to
                          //  a non-constant variable.
const int& d = aConstInt; // This will work because we are trying
                          //  to access a constant variable 
                          //  through a constant reference.
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,可以通过区分 int 引用和 const int 引用来实现一些有用的行为(即,当需要常量引用类型时,不允许创建非常量引用)。