Ответ 1
Вы не указали правильный тип параметра виртуальной функции и, таким образом, вы не переопределяете его. Это приводит к абстрактному классу, поскольку виртуальная функция чиста.
При указании параметра константного ссылочного типа, как
void doStuff(const int & value) {}
это на самом деле альтернатива написанию
void doStuff(int const & value) {}
который следует считать "нормальным" способом объявления постоянной ссылки. При чтении справа налево это означает "ссылка на константу int
". Применение одного и того же шаблона к типу указателя int*
приводит к
void doStuff(int* const & value) {}
который компилируется отлично. Но это невозможно записать в порядке, как описано выше, поскольку это будет означать что-то другое: прочитайте const int* &
справа налево, и вы получите "ссылку на указатель на константу int
".
Как вы упомянули, альтернативу, которая работает с порядком сверху, может быть записана, если вы используете typedef для псевдонима типа указателя int*
:
typedef int *T;
void doStuff(const T & value) {}
который также компилируется отлично, так как T
теперь рассматривается как один тип литерала, не вводящий двусмысленности сверху. Другими словами, единственный способ читать const T &
- это "ссылка на const T
, которая сама является указателем на int
". Это немного сложно понять интуитивно, но невозможно понять это как "ссылку на указатель на константу int
", так как в описании не было бы одного T
.
Я рекомендую использовать ключевое слово override
, если вы используете компилятор С++ 11 для обнаружения таких проблем (есть сценарии, в которых эта проблема не будет приводить к ошибке компиляции, а в непредвиденном поведении; например, если виртуальная функция не была чистой):
void doStuff(int* const & value) override {}
// ^^^^^^^^