2013-06-10 1 views
5

У меня есть код:Перегрузка на 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; 
} 

Приведенный выше код показывает перегрузки в зависимости от того являются Const/летучее параметры. Однако, если бы мне пришлось изменять параметры от int& до int, код больше не компилируется, и я не могу перегружать на основе типов параметров const/volatile. Я не понимаю, почему мы можем перегружать на основе const и volatile, если int передается по ссылке, но не в том случае, если он передан по значению?

EDIT Я должен подчеркнуть, что я понимаю, что такое ссылка. Я не понимаю, почему ссылочный псевдоним разрешен для перегрузки по const, но нормальный int не является.

ответ

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 const).

Далее мы будем смотреть на то, что происходит, когда проходит первый набор переменных для ссылок:

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 reference и const int reference (т. е. запрет на создание непостоянной ссылки при ожидаемом постоянном ссылочном типе).

13

Проблема заключается в том, что верхний уровень const и/или volatile игнорируются при разрешении перегрузки. Так

void foo(const int); 

точно так же, как

void foo(int); 

и аналогично для volatile. Это правило языка, и это имеет смысл, поскольку аргументы передаются по значению. С другой стороны, ссылка на const/volatile или указатель на const/volatile имеет другое значение: вам не разрешено вызывать неконстантные/изменчивые методы по тому, на что они ссылаются или указывают. Здесь constvolatile не являются верхним уровнем.

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 

В двух вышеприведенных декларациях имеется очень разная семантика, поэтому язык делает их отличными от разрешения перегрузки.

+0

Не могли бы вы рассказать о различии между int & и int? Я думал, что ссылка является просто псевдонимом для другой переменной? Итак, int & и int ничем не отличаются? Один просто означает псевдоним? – user997112

+1

@ user997112 Когда вы используете ссылки, копия не производится. Когда вы используете простой pass-by-value, аргумент копируется. –

+0

@ user997112 Я попытался уточнить.В ссылочном случае семантика радикально отличается. Для языка полезно иметь отдельные перегрузки. Не иметь их сбивать с толку. – juanchopanza

Смежные вопросы