说类B
派生自类A
。这两个申报f()
。 f受到保护。因此f只会在A
和B
之内被调用。 f()
需要声明为虚拟吗?虚拟不必要的保护功能
或者说:说C
来自B
来自A
。 B
和A
声明受保护的非虚拟f()
。请拨打f()
C
和B
解决B::f()
和在A到A::f()
?
在这种情况下,我们应该总是避免虚拟受保护的成员有静态解决?这是否自动完成?谢谢!
说类B
派生自类A
。这两个申报f()
。 f受到保护。因此f只会在A
和B
之内被调用。 f()
需要声明为虚拟吗?虚拟不必要的保护功能
或者说:说C
来自B
来自A
。 B
和A
声明受保护的非虚拟f()
。请拨打f()
C
和B
解决B::f()
和在A到A::f()
?
在这种情况下,我们应该总是避免虚拟受保护的成员有静态解决?这是否自动完成?谢谢!
当您需要多态行为(此示例为Template Method pattern)时,声明受保护的方法virtual
是必要的,当您不需要时应避免。然而,在后一种情况下,你不应该用另一个在子类中具有相同签名的函数来遮蔽函数,否则你会感到令人费解的行为(就像你在第2段中描述的那样),这就为微小的错误提供了可能性。
这种情况下,多态行为是什么?是不是假设有一个指向基类的指针?那么这不是按照定义要求公共功能访问吗? – Cookie
@Cookie号在每个函数中,你调用A(从外部)或者你没有在C或B中重载/重载,'this'是一个指向A的指针,所以只有A方法是已知的,如果调用的方法不是虚拟的,则它在运行时不会被解析,您将得到A方法。 –
@Cookie,不,它不需要公共访问。考虑'A'中的公共方法调用'A'中声明的'protected virtual'方法,并在不同的子类中覆盖。您可以通过'protected'方法获得多态行为。有关更多详细信息,请参阅上面对* Template Method *的参考。 –
我在我的C有点生疏++,但我要说的是,当你声明的方法private
,因此你需要virtual
在您的方案protected
在一起“静态解析”只会保证...
你实际上可以有[私人虚拟功能](http:// stackoverflow。com/questions/2170688/private-virtual-method-in-c),它们将被动态绑定。在Java和C#,IIRC中,私有实际上是不可覆盖的,因此是静态绑定的。 – eran
由于只要调用f()
是在A
(而不是过载/在B
或C
中重新实现)的函数中完成的,则this
指针将解析为A*
,因此调用A::f()
。所以不行,在这种情况下你仍然需要一个虚函数。
所以:
class A {
public:
void f() { std::cout << "A::f\n"; }
};
class B : public A {
public:
void f() { std::cout << "B::f\n"; }
};
只要编译器知道的对象实际上是一个B,它会调用F()的B.但是,这并不总是这样:
void callF(A* a)
{
a->f();
}
B b;
callF(&b); // prints A::f
如果您想让callF
等功能调用正确的f()函数,请将其设为virtual
。通常,如果在后代类中重写它们是有意义的,则可以使函数具有虚拟性。受保护的功能通常是这种情况。
对不起,但这个例子假设'f()'是公开的。 – Cookie
如果你用代码来写而不是散文,那会更好。 – PlasmaHH
感兴趣的内容:http://www.gotw.ca/publications/mill18.htm – Flexo