说类B
派生自班级A
。这两个都声明f()
。 f受到保护。因此f只会在A
内和B
内调用。 f()
是否需要声明为虚拟?
或者更确切地说:C
来自B
派生自A
。 B
和A
声明受保护的非虚拟f()
。将来自f()
和C
的{{1}}来电解析为B
而A中的来电是B::f()
吗?
在这种情况下,我们是否应该始终避免虚拟受保护成员具有静态解析?这是自动完成的吗?谢谢!
答案 0 :(得分:2)
只要在f()
派生的函数中完成对A
的调用(并且未在B
或C
中重载/重新实现),{{1指针解析为this
,因此调用A*
。所以不,在这种情况下你还需要一个虚函数。
答案 1 :(得分:1)
当您需要多态行为时,需要声明受保护的方法virtual
(例如Template Method pattern),并且在您不需要时应该避免。但是,在后一种情况下,你不应该在子类中使用具有相同签名的另一个函数来遮蔽函数,否则你会遇到令人费解的行为(就像你在第2段中描述的那样),这可能会产生微妙的错误。
答案 2 :(得分:0)
我的C ++上有点生疏,但我会说只有在声明方法private
时才能保证“静态分辨率”,因此你需要virtual
和protected
一起使用在您的方案中......
答案 3 :(得分:0)
所以:
class A {
public:
void f() { std::cout << "A::f\n"; }
};
class B : public A {
public:
void f() { std::cout << "B::f\n"; }
};
只要编译器知道对象实际上是B,它就会在B中调用f()。但是,情况并非总是这样:
void callF(A* a)
{
a->f();
}
B b;
callF(&b); // prints A::f
如果您希望callF
等函数调用正确的f()函数,请将其设为virtual
。通常,如果在后代类中覆盖它们是有意义的,则将函数设置为虚拟。这通常是受保护功能的情况。