class Base {
public:
virtual void f(float) { cout << "Base::f(float)\n"; }
};
class Derived : public Base {
public:
virtual void f(int) { cout << "Derived::f(int)\n"; }
};
int main() {
Derived *d = new Derived();
Base *b = d;
b->f(3.14F);
d->f(3.14F);
}
Насколько я понимаю, виртуальная таблица класса Derived:
+-----------------+
| Base::f(float) |
+-----------------+
| Derived::f(int) |
+-----------------+
Тем не менее, эта программа выводит:
Base::f(float)
Derived::f(int)
Почему эти два дают разные результаты? я думал b
а также d
должен указывать на ту же виртуальную таблицу.
Это на самом деле не имеет ничего общего с vtables. Derived::f
делает не переопределение Base::f
в этом случае он объявляет новую функцию, которая скрывает Base::f
,
Ты можешь позвонить Base::f
на Derived
экземпляр напрямую с помощью квалифицированного вызова:
d->Base::f(3.14F);
Или вы можете выставить Base::f
с using
директива:
class Derived : public Base {
public:
using Base::f;
virtual void f(int) { cout << "Derived::f(int)\n"; }
};
С using
директива, оба int
а также float
Будут рассмотрены версии:
d->f(3.14F); //calls Base::f
d->f(3); //calls Derived::f
C ++ 11 представил override
спецификатор, чтобы помочь диагностировать проблемы, такие как это. Если вы сделаете следующее изменение:
void f(int) override { cout << "Derived::f(int)\n"; }
тогда g ++ выдает следующую ошибку:
main.cpp:12:18: error:
'virtual void Derived::f(int)' marked 'override', but does not override
Других решений пока нет …