Не путайте переопределение с сокрытием.Вы переопределяете виртуальные.
Ваше определение класса эквивалентно:
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.В общем, переопределение функций базового класса подразумевает сохранение одного и того же возвращаемого типа.Если вы хотите создать новую функцию с другим типом возвращаемого значения, измените ее сигнатуру (либо ее имя, либо параметры - или оба).
В любом случае, вам даже не следует делать это ... Почему быВы хотите иметь функцию с тем же именем и без параметров, возвращающих разные вещи?Не будет ли добавление отдельной функции более читабельным?