关于c ++:受保护函数不需要虚拟

Virtual unnecessary for protected functions

假设类B源于类A。两人都宣布了f()。F受到保护。因此f只能在A内部和B内部调用。f()是否需要声明为虚拟?

或者更确切地说,假设C源于B源于ABA声明受保护的非虚拟f()。在CB中对f()的呼叫是否会解决B::f()和a对A::f()的问题?

在这种情况下,我们是否应该始终避免虚拟的受保护成员具有静态分辨率?这是自动完成的吗?谢谢!


只要对f()的调用是在从A派生的函数中完成(而不是在BC中重载/重新实现),this指针就会解析为A*并因此调用A::f()。所以,在这种情况下,您仍然需要一个虚拟函数。


当您需要多态行为(例如模板方法模式)时,声明您的受保护方法virtual是必要的,而当您不需要多态行为时,则应避免这样做。但是,在后一种情况下,您不应在子类中使用另一个具有相同签名的函数来隐藏该函数,否则会出现令人费解的行为。(就像你在第二段中描述的那样),这为细微的错误打开了可能性。


所以:

1
2
3
4
5
6
7
8
9
10
11
class A {
public:
  void f() { std::cout <<"A::f
"
; }
};

class B : public A {
public:
  void f() { std::cout <<"B::f
"
; }
};

只要编译器知道一个对象实际上是一个b,它就会在b中调用f()。但是,情况并不总是这样:

1
2
3
4
5
6
7
void callF(A* a)
{
  a->f();
}

B b;
callF(&b);  // prints A::f

如果希望像callF这样的函数调用正确的f()函数,则将其设为virtual。通常,如果在子类中重写函数是有意义的,那么可以使函数成为虚拟的。对于受保护的功能,这通常是如此。


我的C++有点生疏了,但是我会说,当你声明方法EDOCX1×1时,只能保证"静态分辨率",因此在你的场景中,你需要EDCOX1,0,EDCOX1,3。