Virtual unnecessary for protected functions
假设类B源于类A。两人都宣布了f()。F受到保护。因此f只能在A内部和B内部调用。f()是否需要声明为虚拟?
或者更确切地说,假设C源于B源于A。B和A声明受保护的非虚拟f()。在C和B中对f()的呼叫是否会解决B::f()和a对A::f()的问题?
在这种情况下,我们是否应该始终避免虚拟的受保护成员具有静态分辨率?这是自动完成的吗?谢谢!
- 型如果你用代码而不是散文写的话会更好。
- 型感兴趣的:gotw.ca/publications/mill18.htm
只要对f()的调用是在从A派生的函数中完成(而不是在B或C中重载/重新实现),this指针就会解析为A*并因此调用A::f()。所以,在这种情况下,您仍然需要一个虚拟函数。
当您需要多态行为(例如模板方法模式)时,声明您的受保护方法virtual是必要的,而当您不需要多态行为时,则应避免这样做。但是,在后一种情况下,您不应在子类中使用另一个具有相同签名的函数来隐藏该函数,否则会出现令人费解的行为。(就像你在第二段中描述的那样),这为细微的错误打开了可能性。
- 在这种情况下,多态行为是什么?这不是假设有一个指向基类的指针吗?那么,根据定义,这不需要公共功能访问吗?
- @cookie编号。在每个函数中,你调用了一个(从外部)或者你没有在C或B中重新实现/重载,this是指向a的指针,因此只有a方法是已知的,如果调用的方法不是虚拟的,那么在运行时它不会被解析,你就得到了a方法。
- @cookie,不,它不需要公共访问。考虑A中的公共方法调用A中声明并在不同子类中重写的protected virtual方法。你可以通过protected方法获得多态行为。有关详细信息,请参阅上面的模板方法参考。
- 干杯谢谢,这很有道理
所以:
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。
- 您实际上可以在C++中拥有私有虚拟函数,它们将被动态绑定。在爪哇和C,Irc,私有企业确实是不可克服的,因此是静态绑定的。