All members of a class--data and methods--are private by default. Private
members can be accessed only within methods of the class itself. Public members
can be accessed through any object of the class. This distinction is both
important and confusing. To make it a bit clearer, consider an example:
unsigned int itsAge;
unsigned int itsWeight;
In this declaration, itsAge, itsWeight, and Meow()
are all private, because all members of a class are private by default. This
means that unless you specify otherwise, they are private.
However, if you write
Boots.itsAge=5; // error! can't access private data!
the compiler flags this as an error. In effect, you've said to the compiler,
"I'll access itsAge, itsWeight, and Meow() only
from within member functions of the Cat class." Yet here you've
accessed the itsAge member variable of the Boots object from
outside a Cat method. Just because Boots is an object of class
Cat, that doesn't mean that you can access the parts of Boots
that are private.
This is a source of endless confusion to new C++ programmers. I can almost
hear you yelling, "Hey! I just said Boots is a cat. Why can't Boots access
his own age?" The answer is that Boots can, but you can't. Boots, in his
own methods, can access all his parts--public and private. Even though you've
created a Cat, that doesn't mean that you can see or change the parts
of it that are private.
The way to use Cat so that you can access the data members is
unsigned int itsAge;
unsigned int itsWeight;
Now itsAge, itsWeight, and Meow() are all public. Boots.itsAge=5
compiles without problems.
The program below shows the declaration of a Cat class with public
public members of a simple class.
1: // Demonstrates declaration of a class and
2: // definition of an object of the class,
4: #include <iostream.h> // for cout
6: class Cat // declare the class object
8: public: // members which follow are public
9: int itsAge;
10: int itsWeight;
14: void main()
16: Cat Frisky;
17: Frisky.itsAge = 5; // assign to the member variable
18: cout << "Frisky is a cat who is " ;
19: cout << Frisky.itsAge << " years old.\n";
Output: Frisky is a cat who is 5 years old.
Analysis: Line 6 contains the
keyword class. This tells the compiler that what follows is a
declaration. The name of the new class comes after the keyword class.
In this case, it is Cat.
The body of the declaration begins with the opening brace in line 7 and ends
with a closing brace and a semicolon in line 11. Line 8 contains the keyword public,
which indicates that everything that follows is public until the keyword private
or the end of the class declaration.
Lines 9 and 10 contain the declarations of the class members itsAge
Line 14 begins the main function of the program. Frisky is defined
in line 16 as an instance of a Cat--that is, as a Cat object. Frisky's
age is set in line 17 to 5. In lines 18 and 19, the itsAge
member variable is used to print out a message about Frisky.
NOTE: Try commenting out line 8 and
try to recompile. You will receive an error on line 17 because itsAge
will no longer have public access. The default for classes is private access.
As a general rule of design, you should keep the member data of a class
private. Therefore, you must create public functions known as accessor methods
to set and get the private member variables. These accessor methods are the
member functions that other parts of your program call to get and set your
private member variables.
New Term: A public accessor
method is a class member function used either to read the value of a
private class member variable or to set its value.
Why bother with this extra level of indirect access? After all, it is simpler
and easier to use the data, instead of working through accessor functions.
Accessor functions enable you to separate the details of how the data is
stored from how it is used. This enables you to change how the data is stored
without having to rewrite functions that use the data.
If a function that needs to know a Cat's age accesses itsAge
directly, that function would need to be rewritten if you, as the author of the Cat
class, decided to change how that data is stored. By having the function call GetAge(),
your Cat class can easily return the right value no matter how you
arrive at the age. The calling function doesn't need to know whether you are
storing it as an unsigned integer or a long, or whether you are
computing it as needed.
This technique makes your program easier to maintain. It gives your code a
longer life because design changes don't make your program obsolete.
Listing 6.2 shows the Cat class modified to include private member
data and public accessor methods. Note that this is not an executable listing.
A class with
1: // Cat class declaration
2: // Data members are private, public accessor methods
3: // mediate setting and getting the values of the private data
5: class Cat
8: // public accessors
9: unsigned int GetAge();
10: void SetAge(unsigned int Age);
12: unsigned int GetWeight();
13: void SetWeight(unsigned int Weight);
15: // public member functions
18: // private member data
20: unsigned int itsAge;
21: unsigned int itsWeight;
Analysis: This class has five public
methods. Lines 9 and 10 contain the accessor methods for itsAge. Lines
12 and 13 contain the accessor methods for itsWeight. These accessor
functions set the member variables and return their values.
The public member function Meow() is declared in line 16. Meow()
is not an accessor function. It doesn't get or set a member variable; it
performs another service for the class, printing the word Meow.
The member variables themselves are declared in lines 20 and 21.
To set Frisky's age, you would pass the value to the SetAge() method,
Frisky.SetAge(5); // set Frisky's age using the public accessor
Declaring methods or data private enables the compiler to find programming
mistakes before they become bugs. Any programmer worth his consulting fees can
find a way around privacy if he wants to. Stroustrup, the inventor of C++, said,
"The C++ access control mechanisms provide protection against accident--not