CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 13 of 13
  1. #1
    Join Date
    Apr 2009
    Location
    Netherlands
    Posts
    91

    Using friend classes can improve encapsulation

    My theory is that using friend classes can improve encapsulation when you use them together with factory and/or manager classes.

    Say I have a class that is to unable to contstruct or initialize itself or I have a factory pattern where it is decided at runtime what object to create. My theory is by making the class that needs to be constructed befriend the manager/factory class will allow you to hide alot of class variables that shouldn't be directly accessed, while still allowing the manager/factory to initilize them.

    This is my view on the subject but I would appreciate some input from other developpers.
    Last edited by AlastrionaAdair; May 4th, 2009 at 05:09 AM.

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

    Re: Using friend classes can improve encapsulation

    Quote Originally Posted by AlastrionaAdair
    Say I have a class that is to unable to contstruct or initialize itself or I have a factory pattern where it is decided at runtime what object to create. My theory is by making the class that needs to be constructed befriend the manager/factory class will allow you to hide alot of class variables that shouldn't be directly accessed, while still allowing the manager/factory to initilize them.
    Why not post example code to illustrate the point that you want to make?
    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

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

    Re: Using friend classes can improve encapsulation

    My theory is by making the class that needs to be constructed befriend the manager/factory class will allow you to hide alot of class variables that shouldn't be directly accessed, while still allowing the manager/factory to initilize them.
    The factory pattern contains pointer to class need to construct. Is there any difference using pointer or friend class declaration ?
    Thanks for your help.

  4. #4
    Join Date
    Apr 2009
    Location
    Netherlands
    Posts
    91

    Re: Using friend classes can improve encapsulation

    Quote Originally Posted by laserlight View Post
    Why not post example code to illustrate the point that you want to make?
    Alright I'll try:

    Code:
    class World {
    public:	
    	
         World();
         void AddSettlement(std::string name, int x, int y); 
    private:
        std::map<std::string, TerrainSquare*> settlements;
        std::vector<std::vector<TerrainSquare>> terrain;
    };
    Code:
    class TerrainSquare {
    public:
    	TerrainSquare();
            Settlement* settlement;
    };
    Code:
    class Settlement  {
    public:
    	Settlement();
    };
    I have this class called World. A World has a terrain which is 2d vector of TerrainSquare objects. It's possible for a TerrainSquare to contain a settlement. However if I had to find a specific settlement I would have to iterate over the entire 2d vector and check if a TerrainSquare contains that settlement. Instead i'm also keeping a map of pointers to TerrainSquares which contain settlements, so I can easily find a specific settlement.

    You will understand that because of this there are alot of actions needed to properly create and add a settlement to the World. Because of this I want the World class to be responsible for creating settlement and properly initializing them and adding them to the World.

    The problem with the above version of the TerrainSquare class is that it all has to have public atributes and constructor in order to allow World to initialize it. I don't consider this good encapsulation as one could still go and create a TerrainSquare or Settlement objects without using the World class. To enforce the use of the World class to create TerrainSqaures and adding Settlements to them, I want to make constructors and attributes of these classes private and let them befriend the World class, thus improving encapsulation.

    Making the classes look like this:

    Code:
    class TerrainSquare {
    	friend class World;
    private:
           TerrainSquare();
            Settlement* settlement;
    
    };
    Code:
    class Settlement  {
            friend class World;
    private:		
    	Settlement();
    };
    I hope this clarifies the point I'm trying to make. I tried to only expose code that would illustrate my problem, because most of these classes have way more atributes and functions but I thought they werent needed to illustrate my point.
    Last edited by AlastrionaAdair; May 5th, 2009 at 06:43 AM.

  5. #5
    Join Date
    May 2009
    Posts
    2,413

    Re: Using friend classes can improve encapsulation

    Quote Originally Posted by AlastrionaAdair View Post
    Say I have a class that is to unable to contstruct or initialize itself or I have a factory pattern where it is decided at runtime what object to create. My theory is by making the class that needs to be constructed befriend the manager/factory class will allow you to hide alot of class variables that shouldn't be directly accessed, while still allowing the manager/factory to initilize them.
    "Friend" creates a strong relationship between classes.

    This means that if "friend" improves encapsulation it also increase the amount of coupling between classes, and that's bad.

    So you seem to have a trade-off situation here. You pay for the better encapsulation by an increased class coupling somewhere else. You got to decide which is the worse evil.

  6. #6
    Join Date
    Apr 2009
    Location
    Netherlands
    Posts
    91

    Re: Using friend classes can improve encapsulation

    Quote Originally Posted by nuzzle View Post
    "Friend" creates a strong relationship between classes.

    This means that if "friend" improves encapsulation it also increase the amount of coupling between classes, and that's bad.

    So you seem to have a trade-off situation here. You pay for the better encapsulation by an increased class coupling somewhere else. You got to decide which is the worse evil.
    Good point. I think that in my situation I can afford to make this design decision though. Are there any alternatives to reach this level of encapsulation that have lower coupling?

  7. #7
    Join Date
    May 2009
    Posts
    2,413

    Re: Using friend classes can improve encapsulation

    Quote Originally Posted by AlastrionaAdair View Post
    Good point. I think that in my situation I can afford to make this design decision though. Are there any alternatives to reach this level of encapsulation that have lower coupling?
    Maybe I've missed something but couldn't you in the shortest possible sentence tell us how your idea would give higher encapsulation?

  8. #8
    Join Date
    Apr 2009
    Location
    Netherlands
    Posts
    91

    Re: Using friend classes can improve encapsulation

    Quote Originally Posted by nuzzle View Post
    Maybe I've missed something but couldn't you in the shortest possible sentence tell us how your idea would give higher encapsulation?
    Actually it doesn't improve encapsulation. Encapsulation is already in place by hiding the creation and workings of the Terrain class behind an interface (the World class). The friend class and private constructor/members would only serve to enforce encapsulation not improve it.

    Your responses have really made me think of the actual value of my design. Which was the point of making this post. I'll have to really ponder if this design offers any significant advantage. But TBH, it won't be too difficult to at a later point remove the friend and make getters/setters public. Shouldn't have to change any other code besides that.

  9. #9
    Join Date
    Oct 2008
    Location
    Singapore
    Posts
    195

    Re: Using friend classes can improve encapsulation

    From your example, it looks like
    1. World object needs access to only the constructor and
    2. only one method (or only a few) methods of World object will need access to that.

    You can increase encapsulation by making only the methods in (2) as friend functions instead of the whole class. But you can't avoid full access to these classes i.e. can't have (1) with friend functions.

  10. #10
    Join Date
    Nov 2006
    Posts
    1,611

    Re: Using friend classes can improve encapsulation

    AlastrionaAdair, I think your inquiry touches on a point I found surprising at first.

    Especially in the earlier days of C++ (late 80's), most of us had the impression that an object was a class, and everything had to be a member function. I don't recall when, but at some point in the early 90's I came across a statement that suggested a looser definition of an object: a collection of data and functions that operate on that data which focus on a single concept or topic (a rough paraphrase).

    This meant that non-member functions which were otherwise part of a functioning unit would be considered part of the object, and you'll discover the STL uses this to some degree. The algorithms are not, generally, member functions. The fact that they are decoupled from containers means they are more generically applicable to various containers. Swap is another example of a non-member function which is more generically applicable outside of a class than inside one.

    To that extent (and again I'm not sure where I read this, it may have been 15 years ago), it may be that several objects form a tight unit, or as a collection form a tight system - a family of objects that work better separately because they are more flexible and generically applicable than would be the case if they were bound into a single class.

    What I think you've found is that in some designs, they may well need to be friends. The point that this couples them tightly should be well considered. This coupling makes them inseparable, and therefore less generic. However, if the concept being modeled defines such coupling, then I think be-friending classes in that family makes sense, especially if you are thinking of them as a group.
    Last edited by JVene; May 16th, 2009 at 09:03 AM.
    If my post was interesting or helpful, perhaps you would consider clicking the 'rate this post' to let me know (middle icon of the group in the upper right of the post).

  11. #11
    Join Date
    Oct 2000
    Location
    London, England
    Posts
    4,773

    Re: Using friend classes can improve encapsulation

    Using friend can increase encapsulation over the alternative of leaving lots of members public because one closely-related class needs access to them.

    In the case of a class whose instances should only be created by a designated factory class, or a special implementation class whose internals are known only by its managing class (the one the user is interacting with) then having the class as a friend can enhance encapsulation.

    The classes do become tightly coupled but sometimes that is because they are, the way the programmer has chosen to implement them, i.e. they form part of a module.

  12. #12
    Join Date
    May 2009
    Posts
    2,413

    Re: Using friend classes can improve encapsulation

    Quote Originally Posted by NMTop40 View Post
    Using friend can increase encapsulation over the alternative of leaving lots of members public because one closely-related class needs access to them.
    That would be what Java would call package-private access. In Java classes can be bunched together in a package. It's possible to limit method access to within a package. In this way classes sharing the same package can fool around with each other easily while maintaining strick access to anyone outside.

    In C++ (to achieve the same as a Java package) everybody in the same "package" would need to declare everybody else a friend, which is very tedious.

    I think it would be nice if C++ introduced something similar to a Java package. It improves encapsulation really. I've seen suggestions in this direction called "modules" or something like it. Unfortunately not for the next version of C++.

  13. #13
    Join Date
    Oct 2000
    Location
    London, England
    Posts
    4,773

    Re: Using friend classes can improve encapsulation

    Remember though that in Java there are no headers and forward declarations so you expose your class implementation to whoever is using the class. Yes you do have interfaces but they are like abstract base classes, i.e. you cannot actually create an instance of one, so you have to expose a concrete class somewhere for someone to create one (even if you use a factory).

    With C++ you can "encapsulate" your class by forward declarations such that nothing actually gets to see the implementation at all other than other classes in the same "module".

    By the way, although friendship is not inherited directly, you can get the friend class to give its children the access to what it wants by making wrapper methods. Thus:

    Code:
    class A
    {
       friend class B;
      private:
        void foo();
    };
    
    class B
    {
      protected:
       void callFoo( A & a )
        {
              a.foo();
        }
    };
    and now any class derived from B can indirectly call A::foo(). So can friends of B which overcomes the issue that friendship isn't transitive.
    Last edited by NMTop40; May 19th, 2009 at 05:58 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