2

Suppose a class: Library

And we have a group of derived class from the base class LibraryCustomer, such as: Kid, Parent, Student, etc

In the class of Library, there are a group of (tons of) private members variables. Since there are tons of private members in the class of Library, I do not want to use getter and setter which are tedious. Plus the LibraryCustomer derived classes will often refer to those members. Getter and Setter are not convenient.

In order for those LibraryCustomers to access those private member in Library, I need to claim those LibraryCustomers as friend classes in Library.

But since the derived classes keep growing, I do not want to add them one by one in the class Library.

Add the base class LibraryCustomer as friend in Library seems not to work. So what is another better way?

[Update] I want to access tons of private member variables in the class of Library. Since there are many, so I do not want to use getter and setter. I hope the derived classes from LibraryCustomer can freely access those private member variables in the class of Library.

user1914692
  • 3,033
  • 5
  • 36
  • 61
  • It is usually bad design to require using friends except in rare cases. What is the actual problem you are trying to solve? There is probably a better design. – Benjy Kessler May 06 '15 at 20:51
  • 1
    How rich is this privileged interface in `Library`? (ie, how many methods are exposed). Or do you really mean members, and we have our consumers directly manipulating the guts of `Library`? – Yakk - Adam Nevraumont May 06 '15 at 20:53
  • What about introducing a protected interface as sketched out here:[How can I remove/refactor a «friend» dependency declaration properly?](http://stackoverflow.com/questions/27492132/how-can-i-remove-refactor-a-friend-dependency-declaration-properly) – πάντα ῥεῖ May 06 '15 at 20:54

1 Answers1

1

Provide a function in LibraryCustomer that accesses Library to get the data and provides that data to the classes derived from LibraryCustomer.

class Library
{
   friend class LibraryCustomer;

   private:

     std::string name;
};

class LibraryCustomer
{
   protected:

   std::string getLibraryName(Library const& lib)
   {
      return lib.name;
   }
};

class Kid : public LibraryCustomer
{
    // Can use LibraryCustomer::getLibraryName() any where
    // it needs to.
};

Having said that, it will be easier to provide access to the data from Library itself.

class Library
{
   public:

      std::string getName() const { return name; }

   private:

     std::string name;
};

Then, there won't be the need for the friend declaration and the wrapper function LibraryCustomer::getLibraryName().

EDIT

@MooingDuck has interesting suggestion. If you have to expose many such variables, it might be better to put them all in one class. Working code at http://coliru.stacked-crooked.com/a/2d647c3d290604e9.

#include <iostream>
#include <string>

class LibraryInterface {
public:
    std::string name;
    std::string name1;
    std::string name2;
    std::string name3;
    std::string name4;
    std::string name5;
    std::string name6;
};

class Library : private LibraryInterface
{
public:
    Library() {name="BOB";}
private:
    LibraryInterface* getLibraryInterface() {return this;} //only LibraryCustomer can aquire the interface pointer
    friend class LibraryCustomer;
};

class LibraryCustomer
{
   protected:
       LibraryInterface* getLibraryInterface(Library& lib) {return lib.getLibraryInterface();} //only things deriving from LibraryCustomer can aquire the interface pointer
};

class Kid : public LibraryCustomer
{
public:
    void function(Library& lib) {
        LibraryInterface* interface = getLibraryInterface(lib);
        std::cout << interface->name;
    }
};

int main() {
    Library lib;
    Kid k;
    k.function(lib);
}
R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • 1
    The problem is how Library access private Kid not the opposite. – Edwin Rodríguez May 06 '15 at 21:03
  • @edwrodrig: Uh, no? I think you got that backwards. The question says the private members are in the Library, and he's friending derived classes so the Kid can access the private members. – Mooing Duck May 06 '15 at 21:09
  • @RSahu: Might be worth mentioning that if there's a lot of such variables, you can use an interface to expose them all togeather: http://coliru.stacked-crooked.com/a/2d647c3d290604e9 – Mooing Duck May 06 '15 at 21:09
  • @RSahu: Thanks. The interface is the function I want. I am just wondering: since all derived classes are from the base class LibraryCustomer, is there any other way related to inheritance, to circumvent this problem? Because I think adding the base class as a friend class seems to be more understandable (unfortunately does not work) – user1914692 May 06 '15 at 22:05
  • @RSahu: (1) Sorry about my misleading. It works. I just ask a further question in my last comment: I am wondering whether there is another simpler way? (2) I read your answer again: since the members in LibraryInterface are public, which is not safe. If members in LibraryInterface are public, I could use assign put those members in Library as public too. So what additional usefulness to add LibraryInterface? – user1914692 May 06 '15 at 22:31
  • @user why do you think public members are not safe? – Yakk - Adam Nevraumont May 07 '15 at 00:09
  • @Yakk, if the public members are safe, so I think I can directly set all those member variables in the class of Library as public, right? I wanted to do this way; just was afraid it was not a good design. – user1914692 May 07 '15 at 00:35
  • @user1914692, providing access to member variables makes your program difficult to maintain. It's always better to provide access the member data through member functions. When you do that, you can even hide how your member data are stored by using the [Pimple idiom](http://en.wikipedia.org/wiki/Opaque_pointer). – R Sahu May 07 '15 at 02:48
  • @RSahu, in your example code, we can access member variables to LibraryInterface freely. It seems a little conflicting.... – user1914692 May 07 '15 at 17:41
  • @user1914692, it is. I copied the code verbatim from the link that was provided by MooingDuck. – R Sahu May 07 '15 at 17:44