On Tue, 05 Oct 2010 12:07:21 -0400, Andrei Alexandrescu <seewebsiteforem...@erdani.org> wrote:

On 10/5/10 7:40 CDT, Steven Schveighoffer wrote:
On Tue, 05 Oct 2010 03:25:03 -0400, Jacob Carlborg <d...@me.com> wrote:

Who says we need to implement it as g++ does? DMD could implement it
to not allow that.


The derived class controls everything. You cannot take control away from
the derived class, it just can't be done:

class A
{
private void cantCallMe();
}

class B : A
{
override private void cantCallMe() { butICanCallYou(); }
private void butICanCallYou() { /* do impl */ }
}

so far, private virtual functions == annoyance. I haven't seen anything
to prove otherwise yet.

-Steve

Private overridable functions come with a guarantee that hooks can never be called from an unknown/uncontrolled context.

And when would a protected hook be callable from an unknown/uncontrolled context? In whose eyes, the base or derived class?

The thing is, any class that defines a private function implementation is able to call it. You can't prevent that. So in the eyes of any base class, it has no way to restrict that. In the eyes of the derived class, it has no control over whether a base class can call it or not. Essentially a private overridable function has one additional guarantee over a protected function -- a derived class cannot call it if it hasn't defined its own version (and isn't in the same module). But that's not the property desired, the property desired for NVI is that *nobody* can call it except the base class, even derived classes. That's simply not possible. So we have to pretend that we can't call it, which is fine, just as easy with protected.

Consider this:

abstract class A
{
  public void myAPIFn() { foo(); }
  abstract private void foo();
}

abstract class B : A
{
  public void bar() {myAPIFn();}
}

class C : B
{
  private void foo() {}
}

So good so far. But I can alter B so it can circumvent myAPIFn by adding its own implementation for foo (which does nothing), and now I'm able to call foo directly from myAPIFn. Basically, even though B does not intend for its version of foo to be the real implementation (knowing that it's abstract and must be derived), it can hijack A's ability to funnel all calls through myAPIFn by simply adding a blank function.

I just don't see the benefit over protected anywhere. You can't say "you're allowed to define this, but you're not allowed to call it." That makes no sense at all, and as I've shown, is impossible to enforce.

-Steve

Reply via email to