Topics
1. Member Access
(Ref. Lippman 13.1.3, 17.2, 18.3)
Types of Access Privilege
| TYPE OF MEMBER | ACCESSIBLE IN CLASS DEFINITION | ACCESSIBLE BY OBJECTS | 
|---|---|---|
| private | yes | no | 
| protected | yes | no | 
| public | yes | yes | 
Member Access Under Inheritance
| INHERITANCE ACCESS SPECIFIER | TYPE OF MEMBER IN BASE CLASS | ACCESS LEVEL IN FIRST DERIVED CLASS | ACCESSIBLE BY FIRST DERIVED CLASS DEFINITION | ACCESSIBLE BY FIRST DERIVED CLASS OBJECTS | 
|---|---|---|---|---|
| private | private protected public | - private private | no yes yes | no no no | 
| protected | private protected public | - protected protected | no yes yes | no no no | 
| public | private protected public | - protected public | no yes yes | no no yes | 
Key Points
- Private members are only accessible within the class that they are declared. They are not accessible by derived class definitions.
- Protected members are not accessible by objects. They are always accessible by a first level derived class.
- The inheritance access specifier places an upper limit on the access level of inherited members in the derived class.
2. A Linked List Class
Class Declaration
list.h
#ifndef _LIST_H_
#define _LIST_H_
#include <iostream.h>
#ifndef TRUE
#define TRUE 1
#endif                          // TRUE
#ifndef FALSE
#define FALSE 0
#endif                          // FALSE
// Generic list element. ListElement is an abstract class which will be
// subclassed by users of the List class in order to create different types
// of list elements.
class ListElement {
        private:
    ListElement *mpNext;        // Pointer to next element in the list.
        public:
    ListElement() {mpNext = NULL;}
    virtual ~ListElement() {}
    // A pure virtual method which returns some measure of the element's
    // importance for purposes of ordering the list. The implementation
    // will be provided by individual subclasses. The list will be ordered
    // from most significant (at the head) to least significant.
    virtual float ElementValue() = 0;
    // A pure virtual method which prints out the contents of the list element.
    // Implementation will be provided by individual subclasses.
    virtual void print() = 0;
    // Grant special access privilege to class list.
friend class List;
    // An operator<< which prints out a list.
friend ostream& operator<<(ostream &os, const List& list);
};
 
// A linked list class.
class List {
        private:
    ListElement *mpHead;        // Pointer to the first element in the list.
        public:
    // Create an empty list.
    List();
    // Destroy the list, including all of its elements.
    ~List();
    // Add an element to the list. Returns TRUE if successful.
    int AddElement(ListElement *pElement);
    // Remove an element from the list. Returns TRUE if successful.
    int RemoveElement(ListElement *pElement);
    // Return a pointer to the largest element. Does not remove it from the list.
    ListElement *GetLargest();
    // Return a pointer to the smallest element. Does not remove it from the list.
    ListElement *GetSmallest();
    // An operator<< which prints out the entire list.
    friend ostream& operator<<(ostream &os, const List& list);
};
#endif // _LIST_H_
Class Definition
list.C
#include "list.h"
// Create an empty list.
List::List() {
    mpHead = NULL;
}
// Destroy the list, including all of its elements.
List::~List() {
    ListElement *pCurrent, *pNext;
    for (pCurrent = mpHead; pCurrent ! = NULL; pCurrent = pNext) {
        pNext = pCurrent->mpNext;
        delete pCurrent;
    }
}
// Add an element to the list. Returns TRUE if successful.
int List::AddElement(ListElement *pElement) {
    ListElement *pCurrent, *pPrevious;
    float fValue = pElement->ElementValue();
    pPrevious = mpHead;
    for (pCurrent = mpHead; pCurrent != NULL; pCurrent = pCurrent->mpNext) {
        if (fValue > pCurrent->ElementValue()) {
            // Insert the new element before the current element.
            pElement->mpNext = pCurrent;
            if (pCurrent == mpHead)
                mpHead = pElement;
            else
                pPrevious->mpNext = pElement;
            return TRUE;
        }
        pPrevious = pCurrent;
    }
    // We have reached the end of the list.
    if (mpHead == NULL)
        mpHead = pElement;
    else
        pPrevious->mpNext = pElement;
    pElement->mpNext = NULL;
    return TRUE;
}
// Remove an element from the list. Returns TRUE if successful.
int List::RemoveElement(ListElement *pElement) {
    ListElement *pCurrent, *pPrevious;
    pPrevious = mpHead;
    for (pCurrent = mpHead; pCurrent != NULL; pCurrent = pCurrent->mpNext) {
        if (pCurrent == pElement) {
            if (pCurrent == mpHead)
                mpHead = pCurrent->mpNext;
            else
                pPrevious->mpNext = pCurrent->mpNext;
            delete pCurrent;
            return TRUE;
        }
        pPrevious = pCurrent;
    }
    // The given element was not found in the list.
    return FALSE;
}
// Return a pointer to the largest element. Does not remove it from the list.
ListElement *List::GetLargest() {
    return mpHead;
}
// Return a pointer to the smallest element. Does not remove it from the list.
ListElement *List::GetSmallest() {
    ListElement *pCurrent, *pPrevious;
    pPrevious = mpHead;
    for (pCurrent = mpHead; pCurrent != NULL; pCurrent = pCurrent->mpNext) {
        pPrevious = pCurrent;
    }
    return pPrevious;
}
// An operator<< which prints out the entire list.
ostream& operator<<(ostream &os, const List& list) {
    ListElement *pCurrent;
    for (pCurrent = list.mpHead; pCurrent ! = NULL;
         pCurrent = pCurrent->mpNext) {
        // Print out the contents of the current list element. Since the
        // print method is declared to be virtual in the ListElement class,
        // the actual print method to be used will be determined at run time.
        pCurrent->print();
    }
}
 
Using the Linked List Class
shapes.h
// Some shapes that we may wish to store in a linked list.
// We will order the shape objects according to their areas.
#ifndef _SHAPE_H_
#define _SHAPE_H_
#define PI 3.14159
#include "list.h"
class Triangle : public ListElement {
        private:
    float mfBase, mfHeight;
        public:
    // Unless we provide an explicit base class initializer, the base
    // class will be initialized using its default constructor.
    Triangle() {mfBase = mfHeight = 0.0;}
    Triangle(float fBase, float fHeight) {mfBase = fBase; mfHeight = fHeight;}
    ~Triangle() {}
    float ElementValue() {return (mfBase * mfHeight / 2);}
    void print() {cout << "Triangle: area = " << ElementValue() << endl;}
};
 
class Rectangle : public ListElement {
        private:
    float mfBase, mfHeight;
        public:
    // Unless we provide an explicit base class initializer, the base
    // class will be initialized using its default constructor.
    Rectangle() {mfBase = mfHeight = 0.0;}
    Rectangle(float fBase, float fHeight) {mfBase = fBase; mfHeight = fHeight;}
    ~Rectangle() {}
    float ElementValue() {return (mfBase * mfHeight);}
    void print() {cout << "Rectangle: area = " << ElementValue() << endl;}
};
 
 
class Circle : public ListElement {
        private:
    float mfRadius;
        public:
    // Unless we provide an explicit base class initializer, the base
    // class will be initialized using its default constructor.
    Circle() {mfRadius = 0.0;}
    Circle(float fRadius) {mfRadius = fRadius;}
    ~Circle() {}
    float ElementValue() {return (PI * mfRadius * mfRadius);}
    void print() {cout << "Circle: area = " << ElementValue() << endl;}
};
#endif                          // _SHAPE_H_
 
list_test.C
#include "shapes.h"
main() {
    List list;
    ListElement *p;
    p = new Triangle(4, 3);
    list.AddElement(p);
    p = new Rectangle(2, 1);
    list.AddElement(p);
    p = new Circle(2);
    list.AddElement(p);
    p = new Triangle(3, 2);
    list.AddElement(p);
    p = new Circle(1);
    list.AddElement(p);
cout << list << endl;
list.RemoveElement(list.GetLargest());
cout << list << endl;
list.RemoveElement(list.GetSmallest());
    cout << list << endl;
}
