Я думаю, что я не понимаю что-то очень базовое понятие о виртуальном поведении. Я хочу создать следующую иерархию:
class Parser{
virtual Parsable parse() = 0;
}
class SpecialParser : public Parser{
SpecialParsable parse() override; // implemented
}
Где явно класс SpecialParsable
наследуется от Parsable
.
Это возвращает мне ошибку из-за другой подписи. (SpecialParser::parse() returns SpecialParsable instead of Parsable)
.
Теперь Parsable явно является абстрактным классом, и я не хочу создавать его экземпляры. Я не понимаю, почему это невозможно сделать, поскольку SpecialParsable - это всего лишь конкретная реализация Parsable.
Заранее спасибо,
См. эта тема, как вернуть объект. И для разных типов возврата SpecialParsable
должен наследоваться от Parseable
, но я думаю, это так?!
Динамический полиморфизм в C++ основан на косвенности. Если вы вернете указатель (или ссылку), ваш пример будет скомпилирован и будет вести себя так, как ожидалось. Это называется "ковариантным возвращаемым типом":
class Parser {
virtual Parsable* parse() = 0;
};
class SpecialParser : public Parser {
SpecialParsable* parse() override; // implemented
};
Есть ли веская причина для этого? Я имею в виду, что если вы вызываете parse()
из указателя/ссылки на базовый класс, то вы все равно не знаете «настоящего» возвращаемого типа. И если вы вызываете его напрямую из производного класса, то зачем делать его виртуальным? Или, если он виртуальный, по какой-то другой причине, то добавление static_cast
к возвращаемому указателю должно быть намного проще...
@sklott: ковариация позволяет использовать наиболее специализированный класс, если вы знаете класс. Из Parser
вы получили только Parsable
, но из SpecialParser
вы можете получить доступ к дополнительным функциям из SpecialParsable
или ограничиться интерфейсом Parsable
.
Они должны возвращать тот же тип.