C++ Public and Private Bob Walton, 7/16/96 A member of a `class' (i.e. a struct) can be `public' or `private'. A public member can be used by any code. A private member can only be used by member functions of the same class, and by functions declared to be `friends' of the class. The keyword `class' is exactly like `struct' except that members are BY DEFAULT private for class and public for struct. Thus given: struct foo { int x; } class bar { int y; } we can have code: main () { foo f; bar b; ... f.x ... // Legal. ... b.y ... // A compile error. In fact, in this case, the y member of `bar' cannot be accessed by any code, as there are no member or friend functions in `bar'. The following would work better: class bar { public: bar ( int y ) { the_y = y; } // Constructor initializing the private // data member `the_y'. int y ( void ) { return the_y; } // Member function returning the value of // the private data member `the_y'. private: int the_y; // A private data member. }; main () { bar b ( 10 ); ... ... b.y() ... // Legal: returns 10. The phrase `public:' says that all members from hence forth on in a class (or struct) are public. Similarly `private:' says that all are private. In the above, `the_y' is private, and can be accessed only by the member functions of `bar'. If a class is declared using the keyword `class' there is an implicit `private:' at the beginning of the class declaration. If a class is declared using the keyword `struct' there is an implicit `public:' instead. Generally it is better to avoid any implicit `public:' or `private:' and use `class' and explicit `public:' and `private:' instead. The syntax `b.y()' is not very nice and one would like to write a function int y ( bar & b ) { return b.the_y; } so one could write 'y ( b )' instead of `b.y()'. But since `the_y' is private, we cannot simply do this. But we can if we make the y function just introduced a `friend' of `bar' by putting friend int y ( bar & b ); inside the declaration of `bar'. Friends of a class can access the private members of the class. Thus we have: .h file: class bar { ... stuff in bar declaration as above ... friend int y ( bar & b ); }; .cc file: int y ( bar & b ) { return b.the_y; } We can also put the code for a friend inside a class declaration, as in: .h file: class bar { ... stuff in bar declaration as above .. friend int y ( bar & b ) { return b.the_y; } }; When we do this, two things happen. First, the code is put into the scope of `bar', so it can use names of static members of `bar' without a `bar::' in front of the names. Our current example makes no use of this. The second thing that happens is the code is declared `inline'. The effect is equivalent to: .h file: class bar { ... stuff in bar declaration as above .. friend int y ( bar & b ); }; inline int y ( bar & b ) { return b.the_y; } It does not matter whether `friend' declarations are placed in the `public:' or `private:' part of a class declaration. As a matter of good style, they should be in the public part if the public is to be allowed to access them, and the private part if they are private to the implementation. Above we have introduced two functions named y. The function `bar::y ( void )' is called as in `b.y()' and the function `y ( bar & b )' is called as in `y ( b )'. Note that because of overloading the types of the arguments are included in the `name' of the function. (The `b' in the name `y ( bar & b )' is not required or significant.) Either of these two functions can be declared separately to be a friend of some other class `mumble': class mumble { . . . . . friend int bar::y ( void ); friend int y ( bar & b ); }; If a function is declared as a friend inside a class in a .h file, it is not necessary to provide a separate declaration for the function outside the class in the .h file, in order for the function to be accessible by code that includes the .h file. The separate outside-class declaration is implicitly provided. It can be rather bothersome to declare all the member functions of one class to be friends of another class, so there is a shorthand for this: class mumble { . . . . . friend class bar; }; This makes all the member functions of `bar' friends of `mumble'. Thus `bar::y ( void )' is made a friend of mumble. But `y ( bar & b )' is NOT: it is not a member function of `bar'. Privacy is supposed to apply to all names that normally begin with a `class qualifier', i.e. a prefix like `bar::' that consists of a class name followed by `::'. Thus in class foo { enum fee { fie, fo, fum }; typedef int bee; struct gee { ... }; . . . . . }; names such as `foo::fee', `foo::fie', `foo::bee', and `foo::gee' are all supposed to be private, and only usable by members and friends of `foo'. However, some implementations (g++) do not respect this rule, and give public access to everything but members (data or functions) of `foo'. There are a number of other problems with the public/private access system and also with current implementations. Because of this, the following ploy is well advised. Begin each .h file with: #ifndef PUBLIC #define PUBLIC public #endif #ifndef PRIVATE #define PRIVATE private #endif and use the words `PUBLIC' and `PRIVATE' in place of `public' and `private' in the rest of the file. Then if a .cc file is having trouble getting at something, it can use the code: #ifdef PRIVATE #undef PRIVATE #endif #define PRIVATE public #include ... #undef PRIVATE to make private data in some included file visible to the .cc file's code.