Почему переменные-члены не могут использоваться в качестве параметров по умолчанию? [дубликат]
Возможный дубликат:
нестатический член как аргумент по умолчанию нестатической функции-члена
Поправьте меня, если я ошибаюсь, но я думаю, что параметры по умолчанию работают следующим образом:
Когда компилятор видит вызов функции, он начинает толкать параметры в стек. Когда у него закончатся параметры, он начнет толкать значения по умолчанию в стек, пока не будут заполнены все необходимые параметры (я знаю, что это упрощение, так как параметры фактически перемещаются справа налево, поэтому он будет начинаться с значений по умолчанию, но идея та же).
Если это верно, то почему переменные-члены не могут использоваться по умолчанию? Мне кажется, что так как компилятор толкает их, как обычно, на сайте вызова, он должен быть в состоянии решить их просто отлично!
EDIT поскольку кажется, что ответы на мой вопрос были неправильно поняты, позвольте мне уточнить. Я знаю, что это так, и я знаю, что разрешено и не разрешено языком. Мой вопрос заключается в том, почему разработчики языка решили не допустить этого, поскольку это, кажется, естественно работает.
4 ответа:
Суть того, о чем вы просите, может быть изложена в этом простом примере
void foo(int a, int b = a);
Это не допускается в C++. C++ не позволяет аргументам по умолчанию зависеть от других параметров.
Использование членов класса в качестве аргументов по умолчанию является лишь частным случаем вышеописанного, поскольку доступ к членам класса осуществляется через указатель
this
, а указательthis
-это просто еще один скрытый параметр каждой нестатической функции-члена.Итак, вопрос действительно в том, почему
void foo(int a, int b = a);
Не является разрешено.
Одна из очевидных потенциальных причин для отказа в этом состоит в том, что это наложило бы дополнительные требования на порядок оценки аргументов. Как известно, в C++ порядок вычисления аргументов функции не определен-компилятор может вычислять аргументы в любом порядке. Однако для того, чтобы поддержать вышеупомянутую функциональность аргумента по умолчанию компилятор должен был бы убедиться, чтоa
вычисляется передb
. Это выглядит как чрезмерное требование, которое ограничивает типичное свобода порядка оценки, которую мы привыкли видеть в C++.Обратите внимание, что это
int a; void foo(int b = a);
Допускается в C++. И, очевидно, он не демонстрирует вышеупомянутый порядок оценки вопроса.
Я считаю, что это наиболее подходящие абзацы из стандарта, особенно §9:
8.3.6 аргументы по умолчанию [dcl.ПКТ.default]
§7 локальные переменные не должны использоваться в аргументе по умолчанию§9 [...] Аналогичным образом, нестатический член не должен использоваться в аргументе по умолчанию, даже если он не вычисляется, если он не отображается как id-выражение выражения доступа к члену класса (5.2.5) или если он не используется для формирования указателя на член (5.3.1).
В этом посте перечислены все способы установки параметра по умолчанию - должны ли параметры функции по умолчанию быть постоянными в C++?
Нетрудно обойти вашу потребность.
class A { int a; public: void f(int i); void f() { f(a); } };
Дает вам то, что вы хотите.
Резюмируя Наваз отличный ответ в связанном вопросе: вызов
void Foo::Bar(int a = this->member)
действительно означаетvoid Foo__Bar(Foo* this, int a = this->member)
. Очевидно, что второй аргумент не может быть вычислен до первого, что нарушает аксиому C++, согласно которой компиляторы могут вычислять аргументы в любом порядке, который им нравится.