2013-02-25 4 views
5

Возникает ли тип возвращаемого значения на переопределение функции? (Насколько я знаю, return typde не является частью сигнатуры функции/метода) В базовом классе у меня есть функция, которая не получает аргументов, возвращает int и является чистой виртуальной. В каждом производном классе я определяю enum для возвращаемого типа. Функция переопределяется в производных классах, то есть имеет одинаковую сигнатуру, но отличается поведением. Вопрос в том, является ли законным для переопределения и возврата тип не является частью функции переопределения?Функция переопределения с различными типами возврата

Пример кода:

class Base 
{ 
    public: 
    typedef int ret; 
    virtual ret method() = 0; 
}; 

class Der1 
{ 
public: 
    enum ret1{ 
    ret1_0, 
    ret1_1 
    }; 
    ret1 method() { return ret1_1;} 
}; 

class Der1 
{ 
public: 
    enum ret2{ 
    ret2_0, 
    ret2_1 
    }; 
    ret1 method() { return ret2_0;} 
}; 
+0

@LihO - Спасибо за ваше примечание. Это была опечатка – Yakov

ответ

4

Вы можете переопределить функции с различными типами возврата, но только ковариантные возвращаемые типы разрешены.

Функция переопределения означает, что либо метод базового класса, либо метод класса Derived будут вызываться во время выполнения в зависимости от фактического объекта, указанного указателем.
Это означает, что:
i.e: Каждое место, где может быть вызван метод базового класса, может быть заменено вызовом метода Derived класса без каких-либо изменений кода вызова.

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

Без этого условия существующий код сломается путем добавления новых функций (новые функции переопределения).

+0

Ваша ковариантная ссылка сломана –

1

то, что у вас есть, не переопределяет.

C++ поддерживает ковариантные типы возврата для необработанных указателей и исходных ссылок.

но вот и все.

1

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

4

Короткий ответ: Нет, это не допускается или лучше поставить его не перекрывая но перезапись, то есть вы не перекрывая Base::method(), но создавая новый метод с таким же именем. Большинство компиляторов предупредит вас об этом. С вашим примером кодом, но при условии, что Base::method является не чисто виртуальным, считаю это:

void callMethod(Base const& b) 
{ 
    auto a1 = b.method(); //what should the type of a1 be? -> it's int. Every time. 
    std::cout << a1 << '\n'; 
} 

int main() 
{ 
    Der1 d1; 
    auto a2 = d1.method(); //a2 is ret1_1 of type ret1 
    callMethod(d1);  //calls Base::method and prints that int, not Der1::method 
} 

Вы права WRT, которые возвращают типы не являются частью сигнатуры функции. Но при переопределении виртуальных функций подпись не так уж важна. §10.3,7 прямо говорится:

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

- оба являются указателями на классы, оба Lvalue ссылка на классы, или оба RValue ссылка для классов

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

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

+0

+1 для цитаты из стандартной – ThomasMcLeod

Смежные вопросы