First Next Previous Last Glossary About

Introducing Classes and Objects in C++ - Part 2

Introduction

class EClassExample
{ public:

  protected:

  private:
};

Declaring a class doesn't differ radically from any other data type declaration. We use a keyword to declare the type of data, we give the "thing" a name and, if necessary, we declare what the members or fields of the new type are.

To declare a class, use the keyword class followed by the name of the class. Then we declare the members of the class if there are any, a class does not have to have members.

You can see that the class can have three sections, these are optional and they determine the accessibility of the class members:

If no sections are declared then, by default, the class contains only private members. The class declaration can contain any number of sections in any order. I wouldn't recommend throwing in sections any old how as general practice.

EClassExample e;

To use a class we create an instance of the class, ie a class variable aka an object. If you are a bit puzzled by the meaning of public, protected and private then keep reading. All will become clear.

class TVModel
{ public:
   void  OnOff();
   toggleswitch IsOn();
   void InitTV();
   void AdjustVolume(int Level);

  protected:
   toggleswitch bOnOffSwitch;
   int nVolumeLevel,
       nChannelNumber,
       nColour,
       nBrightness,
       nContrast;

  private:
};

Here is the TV ADT we have been using but declared as a class.

It has four member functions - OnOff(), IsOn(), InitTV() and AdjustVolume() - which are all publically accessible. The public members are the class interface. It is the public members that provide the interface to the class. The protected and private members provide the class implementation.

It has six data members - bOnOffSwitch, nVolumeLevel, nChannelNumber, nColour, nBrightness, nContrast - which are all protected. They can't be accessed by anything outside the class.

A private section is declared but it is empty.

You can see the member functions are declared but not defined, ie we have said that there will be such things but not what they do.

void TVModel::OnOff()
{if (bOnOffSwitch == ON)
  bOnOffSwitch = OFF;
 else
 if (bOnOffSwitch == OFF)
  bOnOffSwitch = ON;
}

toggleswitch TVModel::IsOn()
{ return bOnOffSwitch; }

void TVModel::InitTV()
{ bOnOffSwitch    = OFF;
  nVolumeLevel    = 0;
  nChannelNumber  = 0;
  nColour         = 0;
  nBrightness     = 0;
  nContrast       = 0;
}

void TVModel::AdjustVolume(int Level)
{ if (IsOn())
   if ((Level < MAXLEVEL) &&
       (Level > MINLEVEL))
    nVolumeLevel = Level;
}

Here are the TV class member functions. They are defined just like any other function except that the function identifier is prefixed with the class name and the scope resolution operator - TVModel::

The OnOff() function toggles the state of bOnOffSwitch.

The IsOn() function returns the state of bOnOffSwitch.

The InitTV() function sets the initial state of a TV.

The AdjustVolume() function sets the volume level of a TV.

The last step for now is to see how we declare an instance of a class and how we use it.



int main()
{ TVModel Akai;
  ...
  
  Akai.InitTV();
  ...

We declare a variable or instance of the class, here I have chosen Akai. Akai is the name of a TV object. Remember the class is a plan for an object.

Now that we have an object we can do things with it.



#include <iostream>
#define MAXLEVEL 100
#define MINLEVEL 0

typedef enum toggleswitch {OFF = 0, ON = 1};

// Class declaration from above
class TVModel
{ public:
   ...
};

//Member function definitions from above

   ...
   
int main()
{ TVModel Akai;
  int count = 0;

  Akai.InitTV();
  for (count = 0; count < 5; count++)
   { Akai.OnOff();
     if (Akai.IsOn())
      cout << "Akai TV is now ON\n";
     else
      cout << "Akai TV is now OFF\n";
   }
 return 0;
}

Here is a simple example which uses the TV class.

I have left the class declarations and definitions out just for brevity.

I have left the class declarations and definitions out just for brevity.

Here is the output generated by the program:

Akai TV is now ON
Akai TV is now OFF
Akai TV is now ON
Akai TV is now OFF
Akai TV is now ON


Tutorial 1

Here is some tutorial work for you.

1 Try the example first to see that it works.

2 Now add this :

  if (Akai.bOnOffSwitch == OFF)
   cout << "Akai TV is now ON\n";
  else
   cout << "Akai TV is now OFF\n";

before the return statement. What do you expect will happen when you compile the program?

3 Add another data member called caseColour. The member should be an integer and should only be accessible to member functions.

4 Add the caseColour field to the InitTV() function then write a member function which displays the case colour.

5 Now add member functions to set and get:



Constructors and Destructors

Whenever we want to use an object it must be constructed. The class is a plan for something we will build and resources - memory - must be allocated to the object. This is achieved by using a constructor function.

The examples you have seen so far showed no explicit constructor for the TV class but one was there by default. You can, and usually do, use one of your own making.

class TVModel
{ public:
   TVModel(toggleswitch,int,int,int,int,int);
   void  OnOff();
   toggleswitch IsOn();
   void AdjustVolume(int Level);
   int  GetVolume();

  protected:
   toggleswitch bOnOffSwitch;
   int nVolumeLevel,
       nChannelNumber,
       nColour,
       nBrightness,
       nContrast;

  private:
   void InitTV(toggleswitch,int,int,int,int,int);
};


TVModel::TVModel(toggleswitch t, int v, int cn,
                 int col, int b, int c)
{ InitTV(t,v,cn,col,b,c);
}

void TVModel::InitTV(toggleswitch t, int v, int cn,
                     int col, int b, int c)
{ bOnOffSwitch    = t;
  nVolumeLevel    = v;
  nChannelNumber  = cn;
  nColour         = col;
  nBrightness     = b;
  nContrast       = c;
}

int main()
{ TVModel Akai(OFF,0,0,0,0,0);
  TVModel Sony(ON, 10,2,3,4,5);
  ...
}

To declare a constructor we have a public member function which has the same name as the class.

You can see it here in the modified class declaration. You can also that InitTV() has been made private. We don't want this publicly accessible now since we will use a constructor.

The constructor is defined and has a parameter list so that whenever we create an object we can initialise the object to whatever kind of tv we want.

The InitTV() function is also modified to take the list of parameters that the constructor hands over when the object is created.

You can see how, in the main() function, an object is declared and given a list of parameters.

A class can also have a destructor which is used to free the resources allocated to the object when it was created.

The function destructor is the name of the class prefixed with a tilde character, eg ~TVModel.

Like the constructor, the destructor is automatically added to the class but you can declare and define your own destructor. I am going to leave that for a little while but will show you later how to use a destructor.



Tutorial 2

1 Modify your work from Tutorial 1 so that it uses a constructor function.



Object Scope

class TVModel
{ public:
   TVModel(toggleswitch,int,int,int,int,int);
   ~TVModel();
   void  OnOff();
   toggleswitch IsOn();
   void AdjustVolume(int Level);
   int  GetVolume();
   static int GetNumberTVs()
    { return nNumber; }
  protected:
   toggleswitch bOnOffSwitch;
   int nVolumeLevel,
       nChannelNumber,
       nColour,
       nBrightness,
       nContrast;
   static int nNumber;
  private:
   void InitTV(toggleswitch,int,int,int,int,int);
};

TVModel::TVModel(toggleswitch t, int v, int cn, 
                 int col, int b, int c)
{ InitTV(t,v,cn,col,b,c);
  nNumber++;
}

TVModel::~TVModel()
{ nNumber--;
}

int TVModel::nNumber = 0;

int main()
{ // Block 1 - the outer block for main()
  cout << "We have " << TVModel::GetNumberTVs() 
       << " tv's " << endl;
  { // Block 1a
    TVModel Akai(OFF,0,0,0,0,0);
    cout << "We have " << TVModel::GetNumberTVs() 
         << " tv's " << endl;
  }
  cout << "We have " << TVModel::GetNumberTVs() 
       << " tv's " << endl;
  { // Block 1b
    TVModel Sony(ON, 10,2,3,4,5);
    cout << "We have " << TVModel::GetNumberTVs() 
         << " tv's " << endl;
    cout << "Volume level is " 
         << Sony.GetVolume() << endl;
  }
  cout << "We have " << TVModel::GetNumberTVs() 
       << " tv's " << endl;
  return 0;
}

Like any other kind of variable, an object is governed by scope ie where is it visible? An object declared inside a function is only visible inside that function.

When an object goes out of scope it is destroyed by the destructor function.

The example shown here has a destructor function and, something you haven't yet seen, some static members. The class has a static data member nNumber, a counter for the number of tv instances, and a static member function GetNumberTVs(), a method which returns the number of tv instances. These members have no real significance except that they help to demonstrate that objects are destroyed when they go out of scope. But ... it is useful to look at static members because they are class members that belong to the class and not to any specific object. This means that static members can be used even when no instance of a class exists.

Note that I have left chunks of the program out, they haven't changed from before.

The constructor includes a statement that increments nNumber and the destructor a statement which decrements nNumber. There is also a statement, outside the class, which initialises the instance counter variable nNumber: int TVModel::nNumber = 0; . This happens in the outer block of the program.

Here is the output:

We have 0 tv's
We have 1 tv's
We have 0 tv's
We have 1 tv's
Volume level is 10
We have 0 tv's


At the start of main() we display the number of instances by sending a message to the TVModel class -> TVModel::GetNumberTVs(). Since there are no TV instances yet, there is no object to send a message to but since we have static members we can use them, they exist even though there are no instances of TVModel. In a sense the static members are like global identifiers except that their scope is limited to the class.

Next the program creates an object TVModel Akai(OFF,0,0,0,0,0) but inside a block embbeded in main's block. We display the count of instances which is now 1. Then the block is closed, we display the instance count again and we are back to 0. The Akai instance has been destroyed.

This is repeated with Sony object.



Tutorial 3

1 Modify your work from Tutorial 2 so that it uses the static members introduced in this topic. Test your program to ensure that it runs.

2 Add a statement to your program that shows that the Akai object is not available outside its block.

First Next Previous Last Glossary About


Copyright © 1999 - 2001 David Beech