Почему объявление функции с аргументом const позволяет вызывать функцию с неконстантным аргументом? - PullRequest
12 голосов
/ 10 сентября 2010

Обратите внимание на следующий код C ++:

#include <iostream>
using std::cout;

int foo (const int);

int main ()
{
   cout << foo(3);
}

int foo (int a)
{
   a++;
   return a;
}

Обратите внимание, что прототип foo() принимает const int, а определение - int. Эта компиляция без ошибок ...

Почему нет ошибок компиляции?

Ответы [ 4 ]

33 голосов
/ 10 сентября 2010

Поскольку для вызывающей функции foo не имеет значения, изменяет ли foo свою копию переменной или нет.

В частности, в стандарте C ++ 03 следующие 2 фрагмента объясняют, почему:

C ++ 03 Раздел: 13,2-1

Два объявления функций с одинаковыми именами ссылаются на одну и ту же функцию, если они находятся в одной области видимости, и иметь эквивалентные объявления параметров (13.1).

C ++ 03 Раздел: 13,1-3

Объявления параметров, которые отличаются только наличием или отсутствием const и / или volatile, эквивалентны. Только const и volatile спецификаторы типа на самом внешнем уровне спецификации типа параметра игнорируются таким образом; Спецификаторы типа const и volatile, скрытые в спецификации типа параметра, имеют большое значение и могут использоваться для различения объявлений перегруженных функций.

13 голосов
/ 10 сентября 2010

Верхний уровень const (то есть, который применяется к переданному значению, а не к чему-то, на что он указывает или ссылается) влияет только на реализацию, а не на интерфейс функции. Компилятор игнорирует его с точки зрения интерфейса (т. Е. Вызывающей стороны) и применяет его только к реализации (т. Е. Коду в теле функции).

2 голосов
/ 10 сентября 2010

Как уже объяснили другие, Стандарт говорит, что все в порядке, и что компилятор может позволить себе проявлять снисходительность в отношении принудительного применения этого, потому что это не влияет на вызывающую сторону, но никто не ответил, почему компилятор следует выбрать, чтобы быть снисходительным. В целом это не особенно снисходительно, и программист, который только что посмотрел на интерфейс, а затем погружается в реализацию, может вспомнить, что параметр является константным, когда он не равен или наоборот - не очень хорошая вещь.

Это снисходительность позволяет вносить изменения в реализацию без изменения заголовков, что при использовании традиционных инструментов make вызывает перекомпиляцию клиентского кода. Это может быть серьезной проблемой при разработке масштаба предприятия, когда несущественные изменения в низкоуровневом заголовке (например, ведение журнала) могут привести к перестройке практически всех объектов между ним и приложениями ... тратить тысячи часов процессорного времени и задержка всех и всего, ожидающего сборки.

Итак, это некрасиво, но практическая уступка.

Я также ответил на другой похожий вопрос, в котором рассматривается, почему перегрузка f (const T) и f (T) недопустима - может представлять интерес для любого, кто читает это - const верхнего уровня не делает t влияет на сигнатуру функции

0 голосов
/ 10 сентября 2010
int foo (const int a)
{
   a++;
   return a;
}

Это приведет к ошибке при компиляции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...