2.3.  Member Access Specifiers

[ fromfile: classes.xml id: memberaccess ]

Thus far you have worked with class definition code kept in header files that contain class definitions and other declarations, and with class implementation code kept in the header's corresponding .cpp files that contain definitions missing from the header file. There is a third category of code as it relates to a given class. Client code is code that is outside the scope of the class, but which uses objects or members of that class. Generally, client code #includes the header file that contains the class definition. In Example 2.5, you can see that fraction.h contains class definition code of Fraction, and is itself a client of QString.

Example 2.5. src/classes/fraction/fraction.h

#ifndef _FRACTION_H_ 
#define _FRACTION_H_  

#include <QString>


class Fraction {
public:
    void set(int numerator, int denominator);
    double toDouble() const;
    QString toString() const;
private:
    int m_Numerator;
    int m_Denominator;
};

#endif


The access specifiers, public, protected, and private, are used in a class definition to specify where in a program the affected members can be accessed. The following list provides an informal first approximation of the definitions of these three terms. Refinements are contained in footnotes.

Class members are private by default. If there is no access specifier preceding a member declaration in a class definition, the member is private.

Example 2.6 uses some Fraction client code to demonstrate accessibiliby and visibility errors in a variety of ways. This example also focuses on block scope. A variable (not a class member) declared inside a block is visible and accessible only between its declaration and the closing brace. In the case of a function, the block that contains the function definition also includes the function's parameter list.

Example 2.6. src/classes/fraction/fraction-client.cpp

#include <QTextStream>
#include "fraction.h"

int main() {
    const int DASHES = 30;
    QTextStream cout(stdout);
    
    {                                   1
        int i;
        for (i = 0; i < DASHES; ++i)
            cout << "=";
        cout << endl;
    }   

    cout << "i = " << i << endl;        2
    Fraction f1, f2;
    f1.set(3, 4);
    f2.set(11,12);                      3
    f2.m_Numerator = 12;                4
    cout << "The first fraction is: " << f1.toString() << endl;
    cout << "\nThe second fraction, expressed as a double is: "
         << f2.toDouble() << endl;
    return 0;
}

1

Nested scope, inner block.

2

Error: i no longer exists, so it is not visible in this scope.

3

Set through a member function.

4

Error, m_Numerator is visible but not accessible.


The relationship between struct and class in C++ can now be clearly described. Stroustrup defines a struct to be a class whose members are by default public, so that

 struct T { ... 

is equivalent to:

 class T {public: ...  

In particular, a struct in C++ can have member functions and data. C++ programmers tend to prefer using class instead of struct for most purposes, perhaps because of its bias in favor of private access. struct seems to be used mostly for applications in which data items need to be grouped together but member functions are not needed.



[23] public static members can be accessed without an object. We discuss this in Section 2.9.

[24] Chapter 6 discuss derived classes.

[25] Private members are also accessible by friends of the class, which we discuss in Section 2.6.