Виртуальный метод вызывает ошибку компиляции в производном классе - PullRequest
2 голосов
/ 01 сентября 2011

Рассмотрим следующий код:

#include <iostream>
using namespace std;

class A
{
public:
    virtual int f() {cout <<"A:: f()\n"; return 1;}
    virtual void f(int) {cout <<"A:: f(int)\n";}
    virtual void g() {cout <<"A::g()\n";}
};

class B3 : public A
{
public:
    void f() {cout <<"B3::f ()\n";}
};

int main()
{
    return 0;
}

Выдает следующую ошибку:

..\main.cpp:17: error: conflicting return type specified for 'virtual void B3::f()'
..\main.cpp:9: error:   overriding 'virtual int A::f()'

а почему? в худшем случае я думаю, что у меня будет Hiding, но вместо этого я получаю ошибку компиляции относительно A's virtual int f() {cout <<"A:: f()\n"; return 1;}

спасибо, Ронен

Ответы [ 2 ]

0 голосов
/ 01 сентября 2011

Вы бы скрылись, если бы f() имел другой список параметров или не был бы объявлен как виртуальный в базовом классе.В первом случае, поскольку перегрузка не пересекает границы наследования, A f было бы скрыто.Но это не так, поскольку у вас есть f() в обоих классах, которые отличаются только возвращаемым значением.Единственная допустимая разница - ковариация возвращаемых значений, и поскольку это не так (void не наследует от int), вы получите ошибку.

0 голосов
/ 01 сентября 2011

Не путайте переопределение с сокрытием.Вы переопределяете виртуальные.

Ваше определение класса эквивалентно:

class B3 : public A
{
public:
    virtual void f() {cout <<"B3::f ()\n";}
};

Как только функция объявлена ​​виртуальной, она останется виртуальной для всех классов, производных от вашего базового класса, независимо от того, явно ли выобъявить это виртуальным или нет.Поэтому вы пытаетесь переопределить виртуальную функцию и изменить ее тип возвращаемого значения, что недопустимо в C ++.Если бы функция не была виртуальной, вы бы просто скрывали реализацию базового класса, поэтому изменение типа возвращаемого значения допустимо.Не было бы никакой двусмысленности, так как компилятор знал бы, откуда вызывать функцию и какой тип возвращаемого значения ожидать.

Однако подумайте о том, чтобы иметь:

A* a;
....
a->f();

Что вернет af ()?a является указателем на A, но может указывать на объект типа B3.Так что либо возвращает int, либо ничего не возвращает.Видите здесь двусмысленность?

Вместо этого, без полиморфизма,

A a;
a.f();

будет вызывать f из a, так же как b3.f будет вызывать f из B3.В общем, переопределение функций базового класса подразумевает сохранение одного и того же возвращаемого типа.Если вы хотите создать новую функцию с другим типом возвращаемого значения, измените ее сигнатуру (либо ее имя, либо параметры - или оба).

В любом случае, вам даже не следует делать это ... Почему быВы хотите иметь функцию с тем же именем и без параметров, возвращающих разные вещи?Не будет ли добавление отдельной функции более читабельным?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...