Почему я не могу иметь типы возврата, ковариантные с void *?

Почему следующий код является ковариационной ошибкой? не T * ковариантный с void *…?

struct Base { virtual void *foo(); };
struct Derived : Base { int *foo(); };

GCC говорит:

invalid covariant return type for 'virtual int* Derived::foo()'

7

Решение

[class.virtual] / p7, акцент мой:

Тип возврата переопределяющей функции должен быть идентичным
тип возврата переопределенной функции или ковариант с
классы функций. Если функция D::f переопределяет функцию
B::fвозвращаемые типы функций ковариантны, если они
удовлетворяют следующим критериям:

  • оба указатели на классы, оба являются lvalue ссылками на классы, или оба rvalue ссылки на классы [сноска опущена]
  • […]

Со страниц 294-5 D&Е:

После некоторого рассмотрения альтернатив мы решили разрешить
переопределение B* по D* и из B& по D& где B является
доступная база D, К тому же, const можно добавить или
вычитается везде, где это безопасно. Мы решили не ослаблять правила
позволяют технически осуществимые преобразования, такие как D к доступным
база B, D для X для которого D имеет преобразование, int* в
void*, double в intи т.д. Мы чувствовали, что выгода от
разрешение таких преобразований путем переопределения не будет перевешивать
стоимость внедрения и возможность сбить с толку пользователей.

7

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

Ковариация между void* а также T* не допускается, потому что:

1. отсутствие согласованности.

Нынешний способ ковариации тривиален для понимания и не создает путаницы.
Просто представьте void* тип ковариации допускается. Для 1 стадии деривации это хорошо, но тогда это создаст путаницу. например.:

struct void_ { virtual void* foo (); };
struct int_ : void_ { virtual int* foo (); };
struct double_ : int_ { virtual double* foo (); };  // int* to double* or void* to double*

В 3-й иерархии struct double_пользователь будет сбит с толку, что хотя double* в int* не возможно, почему код все еще компилируется? Только после проверки самого верхнего класса void_известно, что это из-за double* в void* является «ковариантным». То же самое относится и к компилятору 🙂

2. Проблема со ссылками

В случае занятий, возвращая B&/D*/DD* возможно. Но то же самое невозможно с void& и поэтому int& и т.п.

3. Смешивание ковариаций

Если void* разрешено, то следующее также разрешено непреднамеренно.

struct void_ { virtual void* foo (); };
struct Base : void_ { virtual Base* foo (); };
struct Derived : Base { virtual int* foo (); }; // Look at `int*`

Что приводит к путанице.

1

Ковариантный тип возвращаемого значения — это когда производный класс предоставляет более конкретный / более узкий тип возвращаемого значения для переопределенной функции. Тип возвращаемого производного класса называется ковариантным.

int * не относится к типу void *, тогда как нечто подобное отображает ковариантный тип возвращаемого значения:

struct Base {
virtual void *foo();
virtual Base* func();
};
struct Derived : Base {
//  int *foo();
Derived* func(); //COVARIANT RETURN TYPE
};
0
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector