当我读到Effective C ++时,它说,永远不会在C ++中重新定义非虚函数。
但是,当我测试它时,下面的代码正确编译。那有什么意义呢?这是一个错误还是一个不好的做法?
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;
}
答案 0 :(得分:25)
只要您不依赖于虚拟调度行为,重新定义非虚函数就没问题。
本书的作者害怕您将B*
传递给一个A*
的函数,然后在结果是对基本方法的调用时感到沮丧,而不是派生方法
答案 1 :(得分:7)
试试这个:
int main(){
A *b = new B();
b->f();
return 0;
}
我认为一旦看到结果,答案就会很明显; - )。
如果不是虚拟的,则不会使用后期绑定机制,因此将使用为该指针类型定义的函数,而不是您想要调用的后期绑定函数。这导致了大量难以追踪的错误。
因此,您正在做的是创建一个新功能。 可能是您的意图,但之后阅读您的代码的人可能希望上述代码适用于后期绑定。非常混乱。
我真正希望看到的一个功能是在这种情况下发出警告,使用“重新定义”关键字来预防它,但梦想是梦想,现实就是现实-_-
答案 2 :(得分:2)
关键是,例如,如果您有一个指向基类(List<A *> list
)的指针列表,然后调用f()
,那么B
中重新实现的方法将会不被称为。