说B
类衍生自A
类。它们都声明为f()
。F受到保护。因此,f将只在A
和B
内部调用。f()
需要被声明为虚拟吗?
或者说:C
由B
衍生自A
。B
和A
声明受保护的非虚拟f()
。在C
和B
中对f()
的调用会解析为B::f()
,在a中解析为A::f()
吗?
只要对f()
的调用是在从A
派生的函数中完成的(并且没有在B
或C
中重载/重新实现),this
指针解析为A*
,因此调用A::f()
。所以,在这种情况下,你仍然需要一个虚函数
声明你的保护方法virtual
是必要的,当你想要多态行为(一个例子是模板方法模式),是避免当你不这样做。然而,在后一种情况下,你不应该用子类中具有相同签名的另一个函数来掩盖函数,否则你会得到令人困惑的行为(就像你在第二段中描述的那样),这可能会导致微妙的bug。
我对我的c++有点生锈了,但我想说的是,"静态分辨率"只有在你声明private
方法时才能得到保证,因此你需要virtual
和protected
在你的场景中…
So:
class A {
public:
void f() { std::cout << "A::fn"; }
};
class B : public A {
public:
void f() { std::cout << "B::fn"; }
};
只要编译器知道一个对象实际上是B,它就会在B中调用f()。但是,情况并非总是如此:
void callF(A* a)
{
a->f();
}
B b;
callF(&b); // prints A::f
如果你想让callF
这样的函数调用正确的f()函数,把它改成virtual
。通常,如果在子类中重写函数是有意义的,则将其设置为虚函数。