2011-09-12 58 views
1

说类B派生自类A。这两个申报f()。 f受到保护。因此f只会在AB之内被调用。 f()需要声明为虚拟吗?虚拟不必要的保护功能

或者说:说C来自B来自ABA声明受保护的非虚拟f()。请拨打f()CB解决B::f()和在A到A::f()

在这种情况下,我们应该总是避免虚拟受保护的成员有静态解决?这是否自动完成?谢谢!

+2

如果你用代码来写而不是散文,那会更好。 – PlasmaHH

+0

感兴趣的内容:http://www.gotw.ca/publications/mill18.htm – Flexo

回答

1

当您需要多态行为(此示例为Template Method pattern)时,声明受保护的方法virtual是必要的,当您不需要时应避免。然而,在后一种情况下,你不应该用另一个在子类中具有相同签名的函数来遮蔽函数,否则你会感到令人费解的行为(就像你在第2段中描述的那样),这就为微小的错误提供了可能性。

+0

这种情况下,多态行为是什么?是不是假设有一个指向基类的指针?那么这不是按照定义要求公共功能访问吗? – Cookie

+0

@Cookie号在每个函数中,你调用A(从外部)或者你没有在C或B中重载/重载,'this'是一个指向A的指针,所以只有A方法是已知的,如果调用的方法不是虚拟的,则它在运行时不会被解析,您将得到A方法。 –

+0

@Cookie,不,它不需要公共访问。考虑'A'中的公共方法调用'A'中声明的'protected virtual'方法,并在不同的子类中覆盖。您可以通过'protected'方法获得多态行为。有关更多详细信息,请参阅上面对* Template Method *的参考。 –

0

我在我的C有点生疏++,但我要说的是,当你声明的方法private,因此你需要virtual在您的方案protected在一起“静态解析”只会保证...

+1

你实际上可以有[私人虚拟功能](http:// stackoverflow。com/questions/2170688/private-virtual-method-in-c),它们将被动态绑定。在Java和C#,IIRC中,私有实际上是不可覆盖的,因此是静态绑定的。 – eran

2

由于只要调用f()是在A(而不是过载/在BC中重新实现)的函数中完成的,则this指针将解析为A*,因此调用A::f()。所以不行,在这种情况下你仍然需要一个虚函数。

0

所以:

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。通常,如果在后代类中重写它们是有意义的,则可以使函数具有虚拟性。受保护的功能通常是这种情况。

+0

对不起,但这个例子假设'f()'是公开的。 – Cookie