Страницы

Поиск по вопросам

вторник, 31 декабря 2019 г.

Использование this в методах классов

#cpp


Есть вот такой код:

template
struct somestruct
{
...

T somefunction(somestruct* const th = this)
{
    return th ? th->somefield1 : this->somefield2;
}

...  
};


Компилятор VS 2017 ругается:


  Ошибка    C2355   "this": может указываться только в нестатических
  членах-функциях или инициализаторах нестатических членов данных


Объясните пожалуйста, почему я не могу подобным образом использовать this?

Я хотел бы, чтобы вызов somepointer->somefunction(otherpointer) возвращал поле объекта
указателя из аргумента, если он не nullptr, иначе возвращал другое поле объекта указателя,
вызвавшего метод. А если somefunction вызывается без аргументов, то это было бы аналогично
вызову somepointer->somefunction(somepointer). Конечно, можно делать такой вызов явно
или просто перегрузить somefunction, но интересно, почему нельзя так, как я написал.
    


Ответы

Ответ 1



Короткий ответ: потому что в стандарте языка сказано, что так нельзя. Длинный ответ: в языке С++ не допускается формирование значений аргументов по умолчанию на основе параметров функции. void foo(int a, int b, int c = a + b) // Ошибка { ... } this - это тоже неявный параметр нестатического метода класса, поэтому использовать его для формирования значения аргумента по умолчанию не дозволяется. Причина этого заключается, в частности, в том, что это привело бы в необходимости вычислять параметры функции в некотором "правильном" порядке, а язык С++ не упорядочивает и никогда не упорядочивал вычисление параметров.† Это может быть не единственной причиной такого запрета. Вместо аргумента по умолчанию вы можете просто использовать перегрузку и получить требуемый эффект template struct somestruct { ... T somefunction(somestruct* const th) { return th ? th->somefield1 : this->somefield2; } T somefunction() { return somefunction(this); } ... }; † Начиная с С++17 вычисление аргумента для неявного параметра this упорядочено перед вычислением всех остальных аргументов. Теоретически, это должно было бы устранить вышеописанную проблему с порядком вычисления, но пока что это не привело к изменениям в спецификации использования this в аргументах по умолчанию.

Ответ 2



Возможно, причина заключается в том, что пока компилятор не увидел cv-квалификаторы на методе, тип this неизвестен (т.е. неизвестно, указатель это на константный класс или нет), и поэтому его запрещено использовать до cv-квалификаторов. Пример: struct A { auto f1() const -> decltype(this) {return 0;} // Возвращает `const A *`. auto f2() -> decltype(this) {return 0;} // Возвращает `A *`. decltype(this) f3() const {return 0;} // Ошибка компиляции, т.к. когда компилятор видит // `decltype(this)`, он еще не знает, константный ли это метод, и должен ли `this` быть // `A *` или `const A *`. decltype(this) f3() {return 0;} // Ошибка компиляции, по той же причине. void foo(A * = this) {}; // Опять же, компилятор не знает, имеет ли `this` тип // `A *` или `const A *, поэтому просто не дает его использовать. }

Комментариев нет:

Отправить комментарий