Смешивает ли старый и новый синтаксис функций С++ в допустимом классе?
Этот код действительно работает:
class Abstract {
virtual auto foo() -> int = 0;
};
class Concrete: public Abstract {
int foo() { cout << "blah!" << endl; return 1; }
} instance;
Я понимаю, что функция становится искаженной и привязана к одной и той же сигнатуре функции, но является ли это смешение фактически законным в С++ 14?
Ответы
Ответ 1
auto foo()->int
и int foo()
- это один и тот же прототип, выраженный с различным синтаксисом, поэтому вторая функция является переопределением первого и будет заменять его в диспетчеризации (виртуальной) как обычно.
Синтаксис обратной ссылки справа, обычно имеет другую цель, например
template<class A, class B>
auto some_combination(A a, B b) -> decltype(a+b);
в противном случае требуется более сложный синтаксис, например
temlate<class A, class B>
decltype(std::declval<A>()+std::declval<B>()) some_combination(A a,B b);
так как a
и b
не определены в левой части прототипа.
Если тип возврата тривиально определен, левое или правое размещение по существу не имеет значения.
Ответ 2
Это законно, потому что на самом деле вы полностью определяете свою функцию.
Как минимальный рабочий пример (обратите внимание на override
):
class Abstract {
virtual auto foo() -> int = 0;
};
class Concrete: public Abstract {
int foo() override { return 1; }
} instance;
int main() { }
Здесь тип возврата не выводится, он явно объявляется с помощью возвращаемого возвращаемого типа.
Это эквивалентно:
class Abstract {
virtual int foo() = 0;
};
Было бы иначе, если вы использовали это:
class Abstract {
virtual auto foo() = 0;
};
Здесь задействован вывод шаблона, и виртуальные функции не могут выводить возвращаемый тип (это более или менее строка ошибки из GCC).