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

时间:2013-06-10 21:19:44

标签: c++ const overloading 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;
}

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

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

2 个答案:

答案 0 :(得分:13)

问题是在重载解析中会忽略顶级const和/或volatile。所以

void foo(const int);

完全相同
void foo(int);

,同样适用于volatile。这是一种语言规则,因为参数是按值传递的,所以它是有意义的。另一方面,对const/volatileconst/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

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

答案 1 :(得分:4)

从功能中退一步,查看用例本身也许是有用的。

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

int       anInt     = 1;
const int aConstInt = 1;

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

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

正如您所看到的,没有办法根据行为来解析函数的哪个重载(int int和const int都可以接受const int,同样int也可以接受一个int。 int和一个const int)。

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

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.

正如您所看到的,有一些有用的行为可以区分int引用和const int引用(即当期望常量引用类型时禁止创建非常量引用)。