C ++: ковариантный тип возвращаемого значения без указателя

Я создаю два простых класса по наследству и добавляю виртуальную функцию и переопределение в дочернем классе.

class Parent
{
public:
virtual Parent foo();
};

class Child : public Parent
{
public:
Child foo() override;
};

В этом случае моя переопределенная функция получает ошибку: error C2555: 'Child::foo': overriding virtual function return type differs and is not covariant from 'Parent::foo'

Если я изменю типы возврата с указателем:

class Parent
{
public:
virtual Parent* foo();
};

class Child : public Parent
{
public:
Child* foo() override;
};

ошибка ушла!
Я не понимаю, почему ковариация типов возврата должна быть сделана с указателем, и я не могу использовать тип значения или ссылку.
Некоторые веб-сайты или форумы объясняют, что, поскольку возвращаемое значение является копией значения, используемого в функции, компилятор знает постоянный размер указателя, но должен указывать другой размер для переопределенной функции и родительской функции, что, по-видимому, невозможно.

Итак, почему я не могу использовать ничего, кроме указателя в этом случае?
Если я хочу, чтобы дочерний тип был в переопределенной функции без использования указателей, должен ли я возвращать базовый класс для каждой функции и преобразовывать возвращаемый тип в дочерний тип?

2

Решение

Идея ковариантного возвращаемого типа является полиморфным возвращаемым типом. А в C ++ нельзя иметь полиморфизм во время выполнения без указателей или ссылок. Давайте на секунду проигнорируем большинство трудностей и сделаем вид, что это возможно. Вот мой код, который обрабатывает вещи вашим Parent интерфейс:

void bar(Parent * p) {
auto o = p->foo();
}

Что такое o? Ну, это же Parent конечно. Так говорит в Parent::fooтип возврата. Но что если это p указывает на Child? Выведенный тип o все еще Parentтак что в лучшем случае я получаю нарезанный объект. Никакого полиморфного поведения, поэтому все упражнение бессмысленно.

В худшем случае, и вполне вероятно, я получаю неопределенное поведение.

Вот почему ко-вариантные типы возврата должны быть указателями или ссылками.

5

Другие решения

Это происходит потому, что производный тип будет возвращать производный экземпляр, но вызывающая сторона будет ожидать родителя, это отличается от использования указателей, в случае указателя производный указатель может просто скользить в пространство, зарезервированное для родительского указателя, но то же самое не верно, когда речь идет о реальных случаях. У вас также есть проблема в том, что производный метод будет возвращать производный экземпляр, но вызывающая сторона, использующая родительский указатель, не будет знать об этом и, следовательно, вероятно, уничтожит только родительские части.

ты можешь найти этот полезный

0

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector