Почему переменные-члены не могут использоваться в качестве параметров по умолчанию? [дубликат]


Возможный дубликат:
нестатический член как аргумент по умолчанию нестатической функции-члена

Поправьте меня, если я ошибаюсь, но я думаю, что параметры по умолчанию работают следующим образом:

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

Если это верно, то почему переменные-члены не могут использоваться по умолчанию? Мне кажется, что так как компилятор толкает их, как обычно, на сайте вызова, он должен быть в состоянии решить их просто отлично!

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

4 6

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++, согласно которой компиляторы могут вычислять аргументы в любом порядке, который им нравится.