Переопределить не виртуальную функцию в С++
Когда я читаю Effective С++, он говорит, никогда не переопределяйте не виртуальную функцию в С++.
Однако, когда я его протестировал, код ниже компилируется правильно. Так какой смысл? Это ошибка или просто плохая практика?
class A {
public:
void f() { cout<<"a.f()"<<endl;};
};
class B: public A {
public:
void f() { cout<<"b.f()"<<endl;};
};
int main(){
B *b = new B();
b->f();
return 0;
}
Ответы
Ответ 1
Переопределение не виртуальной функции прекрасно, если вы не зависите от поведения виртуальной диспетчеризации.
Автор книги боится, что вы передадите B*
функции, которая принимает A*
, а затем расстроится, когда результатом будет вызов базового метода, а не производный метод.
Ответ 2
Попробуйте следующее:
int main(){
A *b = new B();
b->f();
return 0;
}
Я думаю, что ответ будет очевиден после того, как вы увидите результат; -).
Не будучи виртуальным, механизм поздней привязки не будет использоваться, поэтому будет использоваться функция, определенная для этого типа указателя, а не функция поздней привязки, которую вы хотите вызвать. Это приводит к множеству плохо отслеживаемых ошибок.
Следовательно, то, что вы делаете, это создание новой функции. Он может быть тем, кем вы намеревались, но кто-то, читающий ваш код впоследствии, может ожидать, что вышеуказанный код будет работать с поздним связыванием. Очень запутанно.
Одна из особенностей, которые я действительно хотел увидеть, - предупреждение в таком случае с ключевым словом "переопределить", чтобы предотвратить его, но мечты - это сны, а реальность - это реальность -_-
Ответ 3
Дело в том, что если вы, например, имеете список указателей на базовый класс (List<A *> list
), а затем вызываете f()
, повторный метод в B
не будет вызываться.