ковариантный тип возврата - PullRequest
2 голосов
/ 29 августа 2010
* * $ 1000 10,3 / 5

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

- оба указателя на классы или ссылки на классы98)

- класс в возвращаемом типе B :: f тот же класс, что и класс в возвращаемый тип D :: f или является однозначный и доступный прямой или косвенный базовый класс класса в тип возвращаемого значения D :: f

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

struct A{};
struct B : A{};

struct X{
    virtual const A * const f(){return 0;}
};

struct Y : X{
    virtual const B * volatile f(){return 0;}
};

int main(){
    Y b;
    X &r = b;
    r.f();
}

Я написал приведенный выше экспериментальный код и нахожу ошибку / предупреждение Comeau неуместной. Предупреждение в строке 9, по-видимому, указывает на то, что квалификатор cv в типе возвращаемого значения не имеет смысла. И именно эта причина приводит к тому, что код плохо сформирован.

"ComeauTest.c", line 5: warning: type qualifier on return type is meaningless
virtual const A * const f(){return 0;}
                  ^

"ComeauTest.c", line 9: warning: type qualifier on return type is meaningless
virtual const B * volatile f(){return 0;}
                  ^

"ComeauTest.c", line 9: error: return type is not identical to nor covariant with
      return type "const A *const" of overridden virtual function function
      "X::f"
virtual const B * volatile f(){return 0;}
                           ^

Итак, вопрос в том, прав ли Комо, давая «предупреждение» в строке 9? Я знаю, что это поведение, определяемое реализацией, и Comeau просто пытается быть милым. Но в этом случае это в лучшем случае сбивает с толку.

1 Ответ

2 голосов
/ 29 августа 2010

Предупреждения в строках 5 и 9 о том, что «квалификатор типа в возвращаемом типе не имеет смысла», связаны с тем, что не относящиеся к классу значения типа r никогда не указываются в cv.

Поскольку результатом функции, возвращающей значение, является значение rvalue, а указатель относится к неклассному типу, возвращаемый указатель не квалифицирован cv, даже если возвращаемый тип говорит, что это так.

Это предупреждение не имеет ничего общего с ковариацией. Следующая функция вызовет то же предупреждение:

int* volatile f() { return 0; }

Что касается процитированного текста из 10.3 / 5:

оба указателя или ссылки имеют одинаковую квалификацию cv

Это относится к квалификации верхнего уровня типа возвращаемого значения (то есть volatile в const int* volatile). Хотя квалификация верхнего уровня не имеет смысла, она влияет на тип функции , поэтому, учитывая объявление f выше, этот фрагмент неверен:

int* (*q)() = f; // error:  can't convert int* volatile (*)() to int* (*)()

Аналогично, если cv-квалификация верхнего уровня возвращаемого типа в функции-члене производного класса не соответствует cv-квалификации верхнего уровня возвращаемого типа в базовом классе, функция-член производного класса не переопределяет функция-член базового класса.

тип класса в типе возврата D::f имеет ту же квалификацию cv, что и квалификация cv или меньше, чем тип класса в типе возврата B::f.

Это относится к квалификации типа класса возвращаемого значения (то есть const в const int* volatile). Это правило означает, что квалификация возвращаемого типа в производной функции-члене класса должна быть равна или меньше, чем квалификация возвращаемого типа функции-члена базового класса, которую она переопределяет.

...