Использование 'override' для функции, которая была объявлена с помощью 'typedef'
C++ 11 представил спецификатор переопределения для функций, и я нахожу его полезным, поскольку он делает его явным, что виртуальная функция переопределяется. Однако я не могу заставить его работать для функции, которая была объявлена с использованием typedef.
Я понимаю, что "переопределение" не является ключевым словом, имеет ли он какое-то отношение к этому?
Следующий код иллюстрирует мою точку зрения:
#include <iostream>
typedef char ReturnsChar();
class Basic
{
public:
virtual char get_a();
virtual ReturnsChar get_z;
};
char Basic::get_a() { return 'a'; }
char Basic::get_z() { return 'z'; }
class Capitalized : public Basic
{
public:
// Can override explicitly if I use the normal definition
char get_a() override;
// Compiles if I use the typedef but not 'override'
ReturnsChar get_z;
// Will not compile, but would like to do this
//ReturnsChar get_z override;
};
char Capitalized::get_a() { return 'A'; }
char Capitalized::get_z() { return 'Z'; }
int main()
{
Basic foo;
Capitalized bar;
std::cout << foo.get_a() << std::endl; // a
std::cout << foo.get_z() << std::endl; // z
std::cout << bar.get_a() << std::endl; // A
std::cout << bar.get_z() << std::endl; // Z
}
Я использую GNU g++ 8.2.0, и ошибка, которую он мне дает, - это
error: expected ';' at end of member declaration
ReturnsChar get_z override;
^~~~~
;
error: ‘override does not name a type; did you mean ‘ctermid?
ReturnsChar get_z override;
^~~~~~~~
ctermid
EDIT: Чтобы ответить на комментарии, я понимаю, что этот стиль неясен. Меня больше интересует, почему это не будет компилироваться и что именно "переопределяет" (особенно потому, что это не ключевое слово). В стороне, я чувствую, что функции typedef-ing могут быть ясными в некоторых случаях, скажем:
void (*foo(int x, void (*f)(int)))(int);
Это трудно читать, особенно если это происходит часто. Я могу просто напечатать это как "UpdateAddressFunction", а затем мысленно подумать о каждой функции этого типа как о том, что "обновляет адрес".
Ответы
Ответ 1
Я понимаю, что "переопределение" не является ключевым словом, имеет ли он какое-то отношение к этому?
Это означает: override
признается только в нескольких конкретных контекстах и доступно в качестве имени для обычного использования в противном случае. Тем не менее, я считаю, что это ошибка компилятора, и это один из контекстов, где компилятор должен распознавать его в своем особом значении.
Соответствующее грамматическое производство для этого
[Class.mem]
член-описатель:
declarator virt-specifier-seq opt pure-specifier opt
Это не требует, чтобы спецификатор virt-seq появился только в объявлении, содержащем параметры. Единственное подобное требование указано ниже:
[Class.mem] P8:
Спецификатор virt-seq должен появляться только в объявлении виртуальной функции-члена (10.3).
В вашем случае объявление является одной из виртуальных функций-членов. Я считаю, что override
должно быть принято здесь.