CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 1 of 2 12 LastLast
Results 1 to 15 of 22

Thread: Accessibility of virtual functions

  1. #1
    Join Date
    Nov 2008
    Location
    England
    Posts
    748

    Question Accessibility of virtual functions

    During a recent discussion on testing regimes I mentioned that on the whole I like to keep my virtuals non-public.

    the relevant thread is :- http://www.codeguru.com/forum/showthread.php?t=469087

    There is some discussion in that thread that relates to this one.

    This is Herb Sutter's view on the subject :- http://www.gotw.ca/publications/mill18.htm

    As you can see he recommends that you should generally set the interface to clients using non-virtual functions that kick down to non-public virtuals so that derived classes can customize behaviour. He feels that the public interface to client code and the interface to derived classes via virtual are distinct concerns. Virtual is for derived class implementors to customize behaviour and client code shouldn't be concerned when a method is called if that method is virtual or not, as long as the method does what its supposed to do the client code should be happy.

    Here is the relevant chapter in Coding Standards that advises the same thing :- http://www.ubookcase.com/book/Addiso...3586/ch39.html

    CPUWizard said that private virtuals make no sense in design and linked the C++ FAQ :- http://www.parashift.com/c++-faq-lit....html#faq-23.4

    This particular FAQ has been the subject of some debates on comp.lang.c++.moderated

    Quote Originally Posted by James Kanze
    That's not misleading; it's completely wrong. I think there's
    pretty much a consensus among the experts that most virtual
    functions should be private---some experts have even gone to the
    point of saying that they should always be private.
    More than just citing a few experts who agree, I think it
    interesting to note that until this FAQ entry, I'd never seen an
    expert who disagreed. (Not everyone would go as far as Herb,
    and say that virtual functions should never be public, but I
    haven't seen anyone condemn the idiom per se.)
    Quote Originally Posted by Jiang
    This FAQ suggests we should keep from using private virtual
    function, because this usage will confuse the C++ newcomers.
    I see the point here, but I can not agree.

    Lets first limit the context to the language itself. It is now well-
    known that class member should be private by default, here
    member means both data member and function member.
    Since virtual member belongs to function member, then the
    virtual member should be private by default, unless in our
    derived class the base version is required.

    IIRC, Herb Sutter & Andrei Alexandrescu explained this issue
    in their "C++ Coding Standards", also James Kanze (together
    with other gurus) showed the same idea quite long time ago.
    I agree with them on this point.

    Another problem for that FAQ is, well, the suggestion/answer
    is based on the assumption that new C++ programmers will
    possibly fail to understand the language at the beginning.
    I do not think this is a good reason because the above
    assumption could be applied to quite a lot of places in C++
    without any change. In my mind, trying to make all kinds
    of mistaken/errors is the best way to master the C++
    language, at least it works for me.
    There appears to be 5 camps of thought on this.
    Quote Originally Posted by Gerhart Menzl
    It depends on what camp you are in. There have been extensive
    discussions on this here, and people seem to be very divided about the
    issue. I have identified at least five camps:
    1. You can do what? You're kidding me!
    2. Okay, I know you can do it, but no honest programmer would. It is
    immoral and a disgrace to the profession.
    3. You can do it, and you should because it is a great tool that helps
    you to fine-tune access levels and maximize encapsulation. Make it
    private in the base class and public in the derived class, or the
    other way round, whatever meets your design needs.
    4. Virtual functions should always be private, never public. Use
    non-virtual public wrappers.
    5. Virtual functions should always be protected, never public. This
    camp is run and populated by James Kanze. <g>

    I used to belong to camp 3, but I see the point of the camp 4 people.
    Interestingly James Kanze has subsequently moved from camp 5 to camp 4.

    This is Nathan Myers thoughts on the subject
    Quote Originally Posted by Nathan Myers
    Defining a public virtual function declares two interfaces,
    a calling interface and a derivation interface. The two have
    different purposes and are used by different code, and as the
    system evolves those purposes may diverge. Defining a public
    non-virtual and a protected virtual function improves modularity,
    and reduces that problem.

    Practically, as James Kanze notes, it allows you to add checks to
    the non-virtual before it calls the virtual. It also allows you to
    do other work in the base-class nonvirtual function that you didn't
    think to specify derived implementations of the virtual interface
    must do.

    In other words, it provides a place to extend the semantics of the
    public function without breaking the implementations of derived
    classes that you don't own. Additional argument checking is one
    example of that.

    As was also noted, if the non-virtuals are also non-inline, then it
    insulates calling code from the layout of the class, which is essential
    in environments where release-to-releasse binary compatibility of
    libraries is required.

    Hence, it's a good idea for several reasons, all connected with
    improving modularity.
    So what do you guys make of all this?
    Should virtual functions generally be nonpublic until the need is proven otherwise?
    Should we make them all public unless we REALLY dont want client code to call them?
    Should we reopen camp 5 now James Kanze has vacated the position?

    What generally do you do with your virtuals?
    Get Microsoft Visual C++ Express here or CodeBlocks here.
    Get STLFilt here to radically improve error messages when using the STL.
    Get these two can't live without C++ libraries, BOOST here and Loki here.
    Check your code with the Comeau Compiler and FlexeLint for standards compliance and some subtle errors.
    Always use [code] code tags [/code] to make code legible and preserve indentation.
    Do not ask for help writing destructive software such as viruses, gamehacks, keyloggers and the suchlike.

  2. #2
    Join Date
    May 2007
    Location
    Scotland
    Posts
    1,164

    Re: Accessibility of virtual functions

    Camp 5 never closed, there are a number of people that hold to it, including Marshall Cline.

    Clearly it is a hotly debated topic, and perhaps both sides (those who say 'private only' and those that don't) have valid points.

    Morally, perhaps it doesn't seem right, since it seems to break the idea that derived classes cannot access private base class members, on the other hand, it is no accident that it has been allowed by the Standard and there are good reasons for taking advantage of it. Consequently, there are companies that ban the practice and companies that mandate the practice (but any company I have worked for so far couldn't seem to care less).

    I have no strong opinion on this particular subject at the moment except to say, that saying virtual functions should always be private (as Gerhart Menzl said) is too strong, since there are occasions where public virtual functions are necessary.

  3. #3
    Join Date
    Apr 1999
    Location
    Altrincham, England
    Posts
    4,470

    Re: Accessibility of virtual functions

    Without getting into the question of whether NVI should be enforced or not, I still tend to stick to one of my basic dicta, which is: "you need a reason to make something non-private".

    So, if I was using NVI, I'd make the virtuals private unless there was a sensible reason to allow the derived override to call the base implementation. For example, a useful idiom is the pure-virtual-with-implementation. The base class provides a default implementation for the function, but the derived class has to explicitly use this default, rather than inherit it accidentally by failing to override a non-pure virtual. Thus, it makes sense to make the pure virtual protected, not private. If the pure virtual has no implementation, then there's no reason to make it non-private, since there's nothing there that any other class can make use of.

    I think I'm probably closest to camp 3, although I'd be a bit more stringent about it: the base function could be private or protected, using criteria such as those outlined above. Derived classes can increase the access restriction of a base class function, but should never make it more open. IOW, a derived class can declare a base protected function as private, but it should never declare a base private function as protected.

    I also disagree strongly with the parashift FAQ. You should never make the concerns of a newbie a reason for introducing a restricted practice. Educate the newcomer - it's quicker and more cost-effective. If we took the line suggested in the FAQ, we'd never use pure-virtuals-with-implementation since, in my experience, some 90+&#37; of new C++ programmers think that pure virtuals can't have an implementation. For the sake of saying "yes, they can", should we restrict a useful idiom?

    Inexperience is transient, knowledge is forever.
    Correct is better than fast. Simple is better than complex. Clear is better than cute. Safe is better than insecure.
    --
    Sutter and Alexandrescu, C++ Coding Standards

    Programs must be written for people to read, and only incidentally for machines to execute.

    --
    Harold Abelson and Gerald Jay Sussman

    The cheapest, fastest and most reliable components of a computer system are those that aren't there.
    -- Gordon Bell


  4. #4
    Join Date
    Nov 2003
    Posts
    1,405

    Re: Accessibility of virtual functions

    Quote Originally Posted by Russco View Post
    So what do you guys make of all this?
    This is discussed in C++ Coding Standards by Sutter & Alexandrescu. It's item 39. "Consider making virtual functions non-public, and public functions nonvirtual. It even has a name, the Nonvirtual Interface pattern (NVI).

    The motivation is that a public virtual function has two orthogonal purposes; A design purpose (it's part of an interface) and an implementation purpose (it can be overriden to change class behaviour). This is why it should be split into two functions, one public nonvirtual and one non-public virtual, each fully devoted to its purpose.

    The advice is to apply NVI "In base classes with a high cost of change (particularly ones in libraries and frameworks)".

    I found NVI a good idea and started applying it everywhere but stopped after a while because I felt it made the code more complex really. Now I will only using it for situations described in the advice.
    Last edited by _uj; January 21st, 2009 at 05:24 AM.

  5. #5
    Join Date
    Nov 2008
    Location
    England
    Posts
    748

    Re: Accessibility of virtual functions

    I have used mostly nonpublic virtuals for a long time, before Herb Sutter wrote his virtuality article. There were 2 parts to this decision. Firstly I became aware of the template method pattern and liked its elegance whereby the interface was specified with an invarient and the behaviour customizable with protected pure virtual functions. Then I thought to myself, whats the point of a protected virtual function when the derived class wont be calling it because it has no implementation so I thought if it works as protected, surely it works as private, tried it out and it worked a treat. This was my introduction to the access v visibility issue. Secondly after consulting stroustrups TCPL I found a general sage advice to make things private wherever possible as it insulates the client code somewhat from changes in the base class as long as the public interface doesn't change. Then I started to realise that it wasn't important to the client code if it called method() or virtual method(). Virtual isn't for client code its for derived implementors, that makes it an implementation detail and as Graham has often said in c++ we spell that p-r-i-v-a-t-e.
    I was chatting about this in PM with CPUWizard and I said that the only time I needed to expose virtuals in the public interface was when I wanted to use covarient return types as it was not possible to trampoline these through an invarient. CPUWizard then brought up COM. This is something I have no experience of, but supposedly COM programmers have to specify there interfaces with public pure virtual functions. So when and if I try my hand at COM programming then I will be forced into public virtuals. Are there other occaisions when you have little choice but to expose virtuals in the public interface?
    Get Microsoft Visual C++ Express here or CodeBlocks here.
    Get STLFilt here to radically improve error messages when using the STL.
    Get these two can't live without C++ libraries, BOOST here and Loki here.
    Check your code with the Comeau Compiler and FlexeLint for standards compliance and some subtle errors.
    Always use [code] code tags [/code] to make code legible and preserve indentation.
    Do not ask for help writing destructive software such as viruses, gamehacks, keyloggers and the suchlike.

  6. #6
    Join Date
    Jan 2008
    Location
    California, USA
    Posts
    822

    Re: Accessibility of virtual functions

    This is a very informative read and educational topic for me.

    In the short course of my learning OO design, all this IS-A/HAS-A/Implementation-in-terms-of relationship sounds too good to be true because that relationship exists on an assumption that all objects are “subject” to serving as a bass class as if it were mandatory. But, that’s not how “objects” in reality behave. I, for example, surely don’t want to share what I have with the person I hate. This means that if I were modeled as an object in OOP, I have no choice but to submit to the iron fist. So hypothetically dreaming, if we can create an object like say
    Code:
    nobase class Mr_Spock {…}
    then, this class can’t be used as a base class, thus is in harmony with the indispensable nature of survival. But then again, this is hardly a polymorphic object in OOP world…but what if this very class exists in a different kind of programming world? The one I call it Substance-Driven (SD) programming.

    In this hypothetical SDP, every object is a combination of pure substance. For example, if we have a pure substance called Ice and Sugar, and we combine this two in a DNA-like sequential process to compound Sugar[2]Ice[10], then we have a new object called Ice Cream, something like
    Code:
    pure Sugar { /* properties of sugar… */ };
    pure Ice { /* properties of ice… */ };
    compound IceCream = Sugar[2] Ice[10];
    where the subscript values of 2 and 10 are the actual “polymorphic” behavior codes.
    Does this make sense to anyone? No? I’m sorry if it didn’t.

  7. #7
    Join Date
    Nov 2003
    Posts
    1,405

    Re: Accessibility of virtual functions

    Quote Originally Posted by potatoCode View Post
    then, this class can’t be used as a base class,
    Java has the keyword final which can be used to declare a class non-inheritable (it cannot be a base class). This puts the decision in the hands of the class designer rather than the user. The designer is in control of the usage of their class which may be a good thing.

    But in practice this is not such a big deal in C++. The rule is simple. Only inherit from classes that were specifically designed to be base classes. It's discussed in C++ Coding Standards by Sutter & Alexandrescu:

    32. Be clear what kind of class you're writing.
    35. Avoid inheriting from classes that were not designed to be base classes.

    I call it Substance-Driven (SD) programming.
    I've seen a lot of SD programming, belive me.

    Code:
    pure Programmer;
    pure Alcohol;
    compound FunnyHacker Alcohol[99] Programmer[1];
    Be careful. Anybody who proposes a language change is required to donate a kidney.
    Last edited by _uj; January 22nd, 2009 at 03:42 AM.

  8. #8
    Join Date
    Jul 2002
    Location
    Portsmouth. United Kingdom
    Posts
    2,727

    Re: Accessibility of virtual functions

    There is a technique for making C++ classes 'final' though I've rarely used it. The developer must have a very good reason to do it before disallowing users of their class from derivation.
    Code:
    template <typename T>
    class MakeFinal
    {
    private:
      ~MakeFinal() { };
      friend T;
    };
    
    class FinalClass : virtual public MakeFinal<FinalClass>
    {
    };
    I'm not sure the above code will be valid for all compilers as I think it is not defined in the C++ spec.

    Quote from "How to write unmaintainable code"
    Make all of your leaf classes final. After all, you’re done with the project - certainly no one else could possibly improve on your work by extending your classes. And it might even be a security flaw - after all, isn’t java.lang.String final for just this reason? If other coders in your project complain, tell them about the execution speed improvement you’re getting.
    "It doesn't matter how beautiful your theory is, it doesn't matter how smart you are. If it doesn't agree with experiment, it's wrong."
    Richard P. Feynman

  9. #9
    Join Date
    Apr 1999
    Location
    Altrincham, England
    Posts
    4,470

    Re: Accessibility of virtual functions

    AFAIAA, that technique won't work with a template, since you can't have template friends, so each "finaliser" has to be specific to the class it's finalising.
    Correct is better than fast. Simple is better than complex. Clear is better than cute. Safe is better than insecure.
    --
    Sutter and Alexandrescu, C++ Coding Standards

    Programs must be written for people to read, and only incidentally for machines to execute.

    --
    Harold Abelson and Gerald Jay Sussman

    The cheapest, fastest and most reliable components of a computer system are those that aren't there.
    -- Gordon Bell


  10. #10
    Join Date
    Jul 2002
    Location
    Portsmouth. United Kingdom
    Posts
    2,727

    Re: Accessibility of virtual functions

    I've read that in the spec it's defined as 'Ill formed', but there are various proposals to make it legal syntax.

    VC++ 2008 accepts the syntax (in anticipation of the change?)
    "It doesn't matter how beautiful your theory is, it doesn't matter how smart you are. If it doesn't agree with experiment, it's wrong."
    Richard P. Feynman

  11. #11
    Join Date
    May 2007
    Location
    Scotland
    Posts
    1,164

    Re: Accessibility of virtual functions

    Possibly, but then Visual Studio accepts other things (possibly also in anticipation???), such as partial/full specialisation of member functions without full specialisation of the parent class.
    Last edited by PredicateNormative; January 22nd, 2009 at 06:49 AM.

  12. #12
    Join Date
    May 2007
    Location
    Scotland
    Posts
    1,164

    Re: Accessibility of virtual functions

    For example, if you uncomment the specialisation, it will still compile under visual studio, but will fail under gcc because it is illegal...

    Code:
    template<typename T>
    class MyClass
    {
    public:
      template<typename Iter_>
      void assign(Iter_ first, Iter_ last)
      {
        std::cout << "Standard" << std::endl;
      }
    
      //template<>
      //void assign<short*>(short* first, short* second)
      //{
      //  std::cout << "Specialised" << std::endl;
      //}
    
    };
    
    int main()
    {
      MyClass<int> m;
      short* p(NULL);
      m.assign(m,m);
      m.assign(p,p);
    
      return 0;
      
    }

  13. #13
    Join Date
    Jan 2008
    Location
    California, USA
    Posts
    822

    Re: Accessibility of virtual functions

    Quote Originally Posted by _uj View Post
    be careful. Anybody who proposes a language change is required to donate a kidney.
    =d

  14. #14
    Join Date
    Jul 2002
    Location
    Portsmouth. United Kingdom
    Posts
    2,727

    Re: Accessibility of virtual functions

    Quote Originally Posted by PredicateNormative View Post
    , but then Visual Studio accepts other things (possibly also in anticipation???), such as partial/full specialisation of member functions without full specialisation of the parent class.
    Does anyone know if there are there technical reasons for these prohibitions or are they just arbitrary?
    "It doesn't matter how beautiful your theory is, it doesn't matter how smart you are. If it doesn't agree with experiment, it's wrong."
    Richard P. Feynman

  15. #15
    Join Date
    Apr 2007
    Location
    Mars NASA Station
    Posts
    1,436

    Re: Accessibility of virtual functions

    I totally agree with Graham here. C++ allow you to anything as you like but the solution may not as intended as you were.

    This has to depends whether it's interface inheritance or implementation inheritance.
    Thanks for your help.

Page 1 of 2 12 LastLast

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  


Windows Mobile Development Center


Click Here to Expand Forum to Full Width




On-Demand Webinars (sponsored)