Переопределить не виртуальную функцию в С++

Когда я читаю 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 не будет вызываться.