Hiding the implementation in c++

10
Hiding the implementation Because I don't want you to know how I do it Daniel Rodríguez (Twitter: @sethillgard)

Transcript of Hiding the implementation in c++

Hiding the implementation

Because I don't want you to know how I do it

Daniel Rodríguez    (Twitter: @sethillgard)

Why?

• In any relationship it’s important to have boundaries that are respected by all parties involved. 

• When you create a library, you establish a relationship with the client programmer who uses that library to build an application or another library.

• You expose an "interface", the client programmer interacts with your library using that interface.

• The client programmer should not change internal data of your library, he could even change something that wasn't intended to change.

Classes

• Each class represnts something on it's own and should provide it's own interface.

• There are two reasons for controlling access to members:o The first is to keep the client programmer’s hands off tools

they shouldn’t touch, tools that are necessary for the internal machinations of the data type, but not part of the interface the client programmer needs to solve their particular problems. This is actually a service to client programmers because they can easily see what’s important to them and what they can ignore.

o The second reason for access control is to allow the library designer to change the internal workings of the structure without worrying about how it will affect the client programmer.

Controlling access to members

• C++ introduces three new keywords to set the boundaries in a structure or class: public, private, and protected.o Members declared as public are part of the class'

interface and thus can be accessed by anyone.o Members declared as private are the inner workings of

the class and nobody can touch them.o Members declared as protected are almost the same as

private members, but they can be handled by classes that inherit from the one in which they were declared.

Example: public

class A{public:      int i;      char j;      void func() { } ;};

A a;a.i = 666;a.j = 'k';a.func();

Example: private

class B{private:      int i;      char j;      void func() { } ;};

B b;b.i = 666;    //Errorb.j = 'k';        //Even more errorb.func();        //You have error on your error

Example: mixing public and privateclass C{private:      int i;public:      char j;      void func() { } ;};

C c;c.i = 666;    //Errorc.j = 'k';        //Ok!c.func();        //Ok too!

Protected?

class Foo{protected:    int a;};class Bar : public Foo{public:    void SetA(int x)    {        a = x;    }};

Foo foo;foo.a = 8; //Error!

Bar bar;bar.a = 8;  //Error!

bar.SetA(8);    //Ok!

Friends

• This mechanism is used to let some classes or functions gain access to provate methods of a class

• Simply use the friend keywordclass X { private:  int i;public:  friend void g(X*, int); // Global friend  friend void Y::f(X*);  // Class member friend  friend class Z; // Entire class is a friend};

Notes on friends

• Friendship is not inherited, NEVER!(I won a coffee out of this)

• There’s no magic way to “break in” from the outside if you aren’t a friend; you can’t declare a new class and say, “Hi, I’m a friend of Bob!” and expect to see the private and protected members of Bob, Bob must declare you as friend first.

• Overall, the use of friend classes, structures or functions is not recommended.