Рейтинг:
33
CPallini
спецификатор виртуальной функции - cppreference.com[^]:
Функция с тем же именем, но другим списком параметров не переопределяет базовую функцию с тем же именем, но скрывает ее: когда поиск неквалифицированного имени проверяет область действия производного класса, поиск находит объявление и не проверяет базовый класс.
Добавление
virtual std::string str() override { return BaseItem::str(); }
для производного класса ваша программа будет компилироваться.
David O'Neil
Спасибо. Это то, что я искал. Не знал, что поиск имен был ограничен таким образом, так что сегодня вечером узнал кое-что новое!
Jon McKee
Да, это был действительно хороший вопрос. Я тоже кое-чему научился. :)
CPallini
- Итак, сегодня вечером я узнал кое-что новое!"
И я тоже (сегодня утром) :-)
Stefan_Lang
И я тоже - не ожидал узнать что-то настолько простое после десятилетий программирования на C++!
Есть 5.
Jon McKee
EDIT: Nvm, теперь я понимаю, что вы имеете в виду CPallini. Добавляя переопределение в производное, вы позволяете перегрузке правильно происходить снова, поскольку обе функции находятся в одной области видимости.
KarstenK
или он удалит виртуальный квалификатор :-O
David O'Neil
Если бы жизнь была так проста! :)
Garth J Lancaster
+5 Карло :-)
Рейтинг:
2
Rick York
Я думаю, что причина, по которой это ошибка, заключается в том, что str не является виртуальным. Производный класс имеет невиртуальный метод str и принимает аргумент. Поскольку вы не прошли ни одного из них, это ошибка. Если вы дадите ему аргумент как есть, я думаю, что вы получите еще одну ошибку, говоря, что функция void ничего не может вернуть.
David O'Neil
Вы правы, что предоставление ему аргумента дает ошибку по другой причине. Интересно также, что создание виртуальной функции производного класса " str "не устраняет проблему, но дает еще один "не принимает 0 аргументов". Есть только два способа исправить это: 1) как я сделал в исходном примере, 2) создать виртуальную функцию в классе DerivedItem, которая просто возвращает функцию BaseItem. Довольно уродливо. Я думал, что поиск имен C++ был более мощным, чем это, но опять же, я никогда раньше не сталкивался с такой ситуацией.
Рейтинг:
1
Espen Harlinn
Привет,
Немного опоздал на вечеринку - но вот идет:
Есть простое решение : добавить using BaseItem::str;
в публичный раздел DerivedItem, например
class DerivedItem : public BaseItem
{
private:
std::string strC;
public:
using BaseItem::str;
void str( std::string s ) { strC = s; }
};
Это позволит выявить все определения
str
от
BaseItem
, независимо от подписи, от
DerivedItem
.
С уважением
Эспен Харлинн
David O'Neil
Спасибо! Отличное дополнение к разговору!
Рейтинг:
0
Richard MacCutchan
В вашем коде есть две простые ошибки:
std::string str = item.str(); //Error. C2660: func doesn't take 0 args.
1. DerivedItem::str требует строку в качестве своего параметра, вы не можете пропустить это.
2. Он объявлен
void
поэтому он не возвращает никакого результата.
Измените эти два, и это сработает.
David O'Neil
Вопрос был в том, почему C++ не способен определить, что функция BaseItem 'str' соответствует этому требованию. Я думал, что это должно быть возможно.
Richard MacCutchan
Проблема просто в том, что вы делаете прямой звонок в DerivedItem::str
с неправильным синтаксисом. В этот момент нет необходимости вызывать базовый класс, поскольку производная функция переопределяет его. Если бы вы вызывали его через указатель, тогда все могло бы быть по-другому. Существует (не необоснованное) описание в Виртуальные Функции | Microsoft Docs[^].