### Defining an Operations Class

To define an operations class, use the predefined templates for standard functions, and define the specific functions individually.

Consider, for example, a person's name (PersonName) and phone number (TNumber). The name serves as the key for an address list, while the phone number serves as the key for a phone list. Because the key function is already defined to yield the person's name, the phone list has to be instantiated in the following way:

#### Header File

This is the header file:

    //person.h - header file containing class Person
    #include <iostream.h>
    #include <istring.hpp>
    #include <istdops.h>

    class Person {
        IString PersonName;
        IString TNumber;

    public:
        //constructor
        Person()
            : PersonName(""), TNumber("")
        {
        }

        //copy constructor
        Person(IString name, IString number)
            : PersonName(name), TNumber(number)
        {
        }

        IString const& GetPersonName() const { return PersonName; }
        IString const& GetTNumber() const { return TNumber; }
        IBoolean operator==(Person const& A) const
        {
             return (PersonName == A.GetPersonName()) &&
                 (TNumber==A.GetTNumber());
        }

        IBoolean operator<(Person const& A) const
        {
            return (PersonName < A.GetPersonName());
        }
    };

    ostream& operator<<(ostream& os, Person A);

    class PhoneOps : public IStdMemOps, public IStdAsOps<Person> {
    public:
        IString const& key(Person const& A) const
        {
            return A.GetTNumber();
        }

        IStdCmpOps <IString> keyOps;
    };

    inline IString const& key(Person const& A)   //Key access
    {
        return A.GetPersonName();
    }

#### Main File

This is the main file:

    //main.cpp - main file
    #include "person.h"   //person.h from the previous example
    #include <istdops.h>
    #include <ikeyset.h>

    typedef IKeySet <Person,IString> AddressList;
    typedef IGKeySet <Person,IString,PhoneOps> PhoneList;

    ostream& operator<<(ostream& os,Person A)
    {
        return (os << endl << A.GetPersonName() <<
            " " << A.GetTNumber());
    }

    void main()
    {
        AddressList Business;
        PhoneList PhoneBook;

        AddressList::Cursor myCursor1(Business);
        PhoneList::Cursor myCursor2(PhoneBook);

        Person A("Peter Black","714-50706");
        Person B("Carl Render","714-540321");
        Person C("Sandra Summers","x");
        Person D("Mike Summers","x");
        Business.add(A);
        Business.add(B);
        Business.add(C);
        Business.add(D);
        PhoneBook.add(A);
        PhoneBook.add(B);
        PhoneBook.add(C);
        PhoneBook.add(D);

        cout << "\n\nPhoneBook before removing an element: ";
        forICursor(myCursor2) {
            cout<<PhoneBook.elementAt(myCursor2);
        }

        cout << "\n\nPhoneBook after removing an element: ";
        PhoneBook.removeElementWithKey("714-50706");
        forICursor(myCursor2) {
            cout<<PhoneBook.elementAt(myCursor2);
        }

        cout << "\n\nBusiness before removing an element: ";
        forICursor(myCursor1) {
            cout<<Business.elementAt(myCursor1);
        }

        cout << "\n\nBusiness after removing an element: ";
        Business.removeElementWithKey("Peter Black");
        forICursor(myCursor1) {
            cout<<Business.elementAt(myCursor1);
        }
    }

The functions that are required for a particular Collection Class depend not only on the abstract class but also on the concrete implementation choice. If you choose a set to be implemented through a hash table, the elements require a hash function. If you choose a (sorted) AVL tree implementation, elements need a comparison function. Even the default implementations may require more functions to be provided than would be necessary for the collection interface.

Introduction to the Collection Classes
Collection Characteristics
Access by Key
Equality Relation
Uniqueness of Entries
Overview of Iteration
Iteration with Cursors
Iteration with allElementsDo
Flat Collections
Trees

Defining Equality Relation
Defining Key or Element Equality
Implementing Element- and Key-Type Functionality
Defining Member Functions of the Element Object Type
Defining Separate Global Functions
Using or Defining an Element Operation Class
Memory Management with Element Operation Classes
Things to Watch Out For
Choosing the Appropriate Smart Pointer Class
Constructing Smart Pointers
Using Element Pointers
Using Cursors to Locate and Access Elements
Instantiating the Collection Classes