Abstract classes compile error

Back to topics list  | 1 2 To post a new topic, please log in or register
avatar
12985
WHRoeder 2016.05.28 13:38 #
 

No, you are missing the point. Virtual and access are independent dimensions. They can be private, and subclasses or external code can still call them through the public/protected non-virtual methods of the base class.

To call one of the world's most noted C++ author "simply wrong" shows your level of ignorance. And when I was reviewing the template chapter of Bjarne Stroustrup 's newest book for publication, I pointed this exact thing out and he agreed and said he would make the indicated change.. If the author of C++ agrees, that really shows your level of ignorance.

avatar
1109
Ovo 2016.05.28 13:59 #
 
WHRoeder:

No, you are missing the point. Virtual and access are independent dimensions. They can be private, and subclasses or external code can still call them through the public/protected non-virtual methods of the base class.

To call one of the world's most noted C++ author "simply wrong" shows your level of ignorance. And when I was reviewing the template chapter of Bjarne Stroustrup 's newest book for publication, I pointed this exact thing out and he agreed and said he would make the indicated change.. If the author of C++ agrees, that really shows your level of ignorance.

Problem is, how the coder of the derived class can learn about such private virtual function. Documentation usually ignores private methods, and the editor won't show them up either. So it is a "hidden feature", if you are not the author of the base class yourself. Sure you can use it, but I doubt it makes the coding life easier or safer.

And here is what other gurus say:

 

Here are the arguments against the "private virtual methods" feature:

  1. private virtual is only useful when you have a nested derived class. This is a useful pattern, but far less common than the non-nested derived class situation.

  2. If you desire to restrict the ability to override the method in non-nested derived classes then you can do so by restricting the ability of non-nested classes to derive from the base class; make all the base class constructors private. Therefore private virtual is not necessary to prevent overriding; protected virtual is sufficient, because the only derived classes will be nested.

  3. If you desire to restrict the ability to call a method in a non-nested derived class then you can make the method internal virtual and then tell your coworkers to not use that method. It is irritating to have this not be enforced by the compiler, but the compiler does not enforce any other semantic constraint on how a method is supposed to be used either; getting the semantics right is your business, not the compiler's, and you have to enforce that with appropriate code reviews. Therefore private virtual is not necessary to prevent calling; internal virtual plus code reviews is sufficient.

  4. It is possible to implement this pattern already with existing parts:

    abstract class C
    {
        private int CF() { whatever; }
        private Func<int> f;
        public C() { f = CF; } 
        private int F() { return f(); }
        private class D : C
        {
            private int DF() { whatever; }
            public D() { f = DF; }
        }

    Now I have a method F which is effectively virtual, but can only be "overridden" by derived nested classes.

Since in every case either protected, internal or protected internal does the trick, private virtual is unnecessary. It's almost never the right thing to do, since you have to be already committed to using the nested derived class pattern. So, the language makes it illegal.

The arguments for are:

There have been times in real code when I've want a virtual method to be a private implementation detail of a class that I want to be extended both by non-nested internal classes and nested internal classes. Having to enforce the invariant that the internal method not be called by my coworkers is vexing; I'd like that to be enforced by the compiler without me having to jump through crazy hoops like making a field of delegate type, etc.

Also, there's simply the matter of consistency and orthogonality. It seems weird that two things that ought to be independent -- accessibility and virtualness -- have an effect on each other unnecessarily.

The arguments against the feature are pretty strong. The arguments for are pretty weak. Therefore, no such feature. I'd personally like it very much, but I totally understand why the design team has never taken me up on it. It's not worth the cost, and I would hate to not ship a better feature because we spent budget on a feature that benefits almost no one.

The second question is "Why in C# are you not able to override a private virtual method in a derived non-nested class?"

There are several reasons.

  1. Because you can only override what you can see. A private method is a private implementation detail of a base class and must not be accessible.

  2. Because allowing that has serious security implications. Remember, in C++ you almost always compile code into an application all at once. You have the source code for everything; everything is essentially "internal" from the C++ perspective most of the time. In C#, that's not at all the case. Third party assemblies can easily get at public types from libraries and produce novel extensions to those classes which can then be used seamlessly in place of instances of the base class. Since virtual methods effectively change the behaviour of a class, any code which depends for security reasons on invariants of that class needs to be carefully designed so that they do not depend on invariants guaranteed by the base class. Restricting accessibility of virtual methods helps ensure that invariants of those methods are maintained.

  3. Because allowing that provides another form of the brittle base class problem. C# has been carefully designed to be less susceptible to the brittle base class problem than other OO languages. If an inaccessible virtual method could be overridden in a derived class then that private implementation detail of the base class becomes a breaking change if altered. Providers of base classes should be free to change their internal details without worrying overmuch that they've broken derived classes which depend on them; ideally only the public, documented interface to a type needs to be maintained when implementation details change.

 

avatar
119
Doerk 2016.05.28 14:11 #
 

As far as I can remember (maybe I am wrong) but Microsoft used exactly the "protected" style for their frameworks when Visual C++ came out. And my respect to the authors, but nevertheless there is another very good reason to use protected instead of private. Normally, its typical to use such virtual functions as event handlers and in most cases without any parameters. The reason for this is not only the better readable code, its also a matter of stack sizing and by this, a matter of performance too.

And there is one more argument which you cannot ignore:

Of course you can call the non private version of the base class, but if you do so, and you decide to change anything in the parameters of the base class, you have to edit/modify all classes which ever derived from the base too. This makes the whole code fragile whenever you are forced to take such a decision for whatever reason.

The world is not only black and white and my posting has nothing to do with ignorance, same way the opinion of a book author is not law and not valid for anything and any circumstance. 

avatar
Moderator
3206
angevoyageur 2016.05.28 14:56 #
 
Ovo:

And here is what other gurus say:

Please use quotes and provide the source(s).
Back to topics list   | 1 2  

To add comments, please log in or register