CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 9 of 9
  1. #1
    Join Date
    Jul 2005
    Posts
    1,030

    virtual breaks encapsulation in C++?

    Here is the code,
    Code:
    class A
    {
       public:
         virtual void foo(){}
    };
    
    class B : public A
    {
       private:
          virtual void foo(){}
    };
    
    void main()
    {
       B b;
       A* pA = &b;
       pA->foo();
     
    }
    Obviously when you call pA->foo, it will call foo defined in B. But foo defined in B is private. It is not supposed to be called outside the class B. So it looks like virtual breaks encapsulation.

  2. #2
    Join Date
    Apr 1999
    Posts
    27,449

    Re: virtual breaks encapsulation in C++?

    Quote Originally Posted by LarryChen View Post
    Obviously when you call pA->foo, it will call foo defined in B.
    pA is not a pointer to B. It is declared as a pointer to A. At compile-time it is the static type that is considered, and the static type is "pointer to A".
    Code:
    class A
    {
       private:
         virtual void foo(){}
    };
    
    class B : public A
    {
       public:
          virtual void foo(){}
    };
    
    int main()
    {
       B b;
       A* pA = &b;
       pA->foo();
    }
    What results do you get with this change? I bet it doesn't even compile.

    Regards,

    Paul McKenzie

  3. #3
    Join Date
    Jun 2010
    Location
    Germany
    Posts
    2,675

    Re: virtual breaks encapsulation in C++?

    Quote Originally Posted by Paul McKenzie View Post
    [...]

    What results do you get with this change? I bet it doesn't even compile.
    I agree (though I didn't try it). I wouldn't even have expected the original code from post #1 to compile. And even if it's possible, I consider changing the visibility of virtual functions when deriving questionable in general.

    In that original code, it's B that breaks its own encapsulation by making the private member function virtual, thereby allowing the base class (about which, ideally, it shouldn't make any assumptions beyond its public and protected interface) to call it. That's the decisiion of B's designer and he simply wouldn't need to do that if he wouldn't want to for some obscure reason. That's it.

    After all, IMO private virtual functions don't make any sense anyway.

    [EDIT:] Ok, one acceptable reason for a private virtual function I can imagine is to seal the function with respect to further derivates, i.e. disallowing them to override the function. And then it would be absolutely intended to allow the base class to call that function. I never encountered a design where I really would have wanted to do that, though.
    Last edited by Eri523; July 18th, 2013 at 08:52 AM.
    I was thrown out of college for cheating on the metaphysics exam; I looked into the soul of the boy sitting next to me.

    This is a snakeskin jacket! And for me it's a symbol of my individuality, and my belief... in personal freedom.

  4. #4
    Join Date
    Aug 2000
    Location
    West Virginia
    Posts
    7,721

    Re: virtual breaks encapsulation in C++?

    Sutter on public vs private virtual functions ...

    http://www.gotw.ca/publications/mill18.htm

  5. #5
    Join Date
    Apr 1999
    Posts
    27,449

    Re: virtual breaks encapsulation in C++?

    Quote Originally Posted by Eri523 View Post
    one acceptable reason for a private virtual function I can imagine is to seal the function with respect to further derivates, i.e. disallowing them to override the function. And then it would be absolutely intended to allow the base class to call that function. I never encountered a design where I really would have wanted to do that, though.
    Here is a scenario:

    The base class has a public execute() function. This function must call virtual functions f1(), f2(), f3(), in that order. Also f1(), f2(), etc. are customized by the derived classes. How do you, at the very least, make it difficult to do the following:

    a) call f1(), f2(), etc. from outside the classes, and
    b) calling f1(), f2() in the wrong order of execution as specified by the requirements.

    The way this is usually done is to declare f1(), f2(), etc. as private virtuals, and have execute() be a non-virtual public function in the base class. This way the derived classes still have customization, but the execution is controlled by the base class.

    Regards,

    Paul McKenzie
    Last edited by Paul McKenzie; July 18th, 2013 at 12:01 PM.

  6. #6
    Join Date
    Jan 2006
    Location
    Singapore
    Posts
    6,765

    Re: virtual breaks encapsulation in C++?

    Quote Originally Posted by LarryChen
    Obviously when you call pA->foo, it will call foo defined in B. But foo defined in B is private. It is not supposed to be called outside the class B. So it looks like virtual breaks encapsulation.
    The interface of B violates the Liskov substitution principle. However, the fact that only the type of pA is considered here saves the day, in a way.
    C + C++ Compiler: MinGW port of GCC
    Build + Version Control System: SCons + Bazaar

    Look up a C/C++ Reference and learn How To Ask Questions The Smart Way
    Kindly rate my posts if you found them useful

  7. #7
    Join Date
    Jun 2010
    Location
    Germany
    Posts
    2,675

    Re: virtual breaks encapsulation in C++?

    Quote Originally Posted by Paul McKenzie View Post
    Here is a scenario:

    The base class has a public execute() function. This function must call virtual functions f1(), f2(), f3(), in that order. Also f1(), f2(), etc. are customized by the derived classes. How do you, at the very least, make it difficult to do the following:

    a) call f1(), f2(), etc. from outside the classes, and
    b) calling f1(), f2() in the wrong order of execution as specified by the requirements.

    The way this is usually done is to declare f1(), f2(), etc. as private virtuals, and have execute() be a non-virtual public function in the base class. This way the derived classes still have customization, but the execution is controlled by the base class.

    Regards,

    Paul McKenzie
    Thanks for outlining that. When initially reading your post, I considered your example an extension of the Non-Virtual Interface idiom (that I've alreay used myself quite a few times), but after reading the excellent article Philip linked to in post #4 I concluded that it exactly is an application of the idiom.

    Now I know my firm belief in private base class member functions being competely invisible to derived clases so they can't be overridden was a misconception that in fact I never questioned since it seemed so logical. So, of course, private virtual functions do make sense. However, most of my virtual functions probably will remain protected, as they've been all the time, since I frequently implement overrides in terms of the base class implentation, applying certain pre-filtering and/or post-processing.

    The idea of making the use of the NVI idiom ones default implementation habit definitely seems to be worth another thought.
    I was thrown out of college for cheating on the metaphysics exam; I looked into the soul of the boy sitting next to me.

    This is a snakeskin jacket! And for me it's a symbol of my individuality, and my belief... in personal freedom.

  8. #8
    Join Date
    Jul 2013
    Posts
    576

    Re: virtual breaks encapsulation in C++?

    Quote Originally Posted by LarryChen View Post
    breaks encapsulation.
    In my view this feature of C++ rather enhances encapsulation; A is the public interface and B is a hidden implementation of A not to be publicly instantiated.

    It would be better if C++ sported a "module" feature but lacking that making all derived implementation classes all private is a good enougth alternative.
    Last edited by razzle; July 22nd, 2013 at 07:01 PM.

  9. #9
    Join Date
    Jul 2013
    Posts
    576

    Re: virtual breaks encapsulation in C++?

    Quote Originally Posted by laserlight View Post
    The interface of B violates the Liskov substitution principle.
    Well, B violates Liskov only if it's intended as a publicly exposed subtype of A. If the sole purpose of B is to be an anonymous implementation of A it doesn't.
    Last edited by razzle; July 21st, 2013 at 09:41 AM.

Posting Permissions

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





Click Here to Expand Forum to Full Width

Featured