Classes and Objects

Classes and Objects:

Object -- an encapsulation of data along with functions that act upon that data.

An object consists of:

  • Name -- the variable name we give it
  • Member data -- the data that describes the object
  • Member functions -- behavior aspects of the object (functions related to the object itself)
  • Class -- a blueprint for objects. A class is a user-defined type that describes what a certain type of object will look like. A class description consists of a declaration and a definition. Usually these pieces are split into separate files.

    An object is a single instance of a class. You can create many objects from the same class type.

    DDU Design - Declare, Define, Use:

    Declare - A declaration gives an interface.  A variable declaration gives the type.  A function declaration tells how to use it, without bothering with how it works.  A class declaration shows what an object will look like and what its available functions are. Again, implementation details aren't needed here.

    Define - A definition usually consists of the implementation details.  This part doesn't need to be seen by the user of the interface.  A function definition is the code that makes a function work (the function body).  A class definition consists definitions of its members.

    Use - The use of an item, through its interface.  The user of an executable program uses the graphic interface, keyboard, and mouse.  The user of a function is a programmer, who makes calls to the function (without needing to know the implementation details).  The user of a class is also a programmer, who uses the class by creating objects and calling the available functions for those objects.

    Note -- The concept of interface is a very important one in object-oriented programming.  The interface is what the user sees.  We often leave the implementation details hidden.  We want to strive to create a clear interface for the user (not necessarily the end user of a program -- could be a programmer, i.e. the user of a class).
     

    Protection levels in a class:

    We can declare members of a class to be public or private.
     
  • public - can be accessed from inside or outside of the object.
  • private - can only be used by the object itself.
  • The public section of a class is essentially the interface of the object.  The user of an object is some other portion of code (other classes, functions, main program).  So, objects are used by programmers, and we want the interface to be as simple as possible.  This usually means providing functions in the public area that handle all of the necessary actions on the object.

    Although there is no set rule on what is made public and what is made private, the standard practice is to protect member data of a class by making it private.  If there are functions that do not need to be part of the interface, then these can be private, as well.

    Reasons for data hiding:

  • Makes interface simpler for user.
  • Principle of least priveledge (need-to-know)
  • More secure.  Less chance for misuse (accidental or malicious).
  • Class implementation easy to change without affecting other modules that use it.

  •  

    Class Declaration Format:

     class <className> 
     { 
     public: 
         (public member data and functions go here) 
     private:
         (private member data and functions go here) 
    
     }; 
    
    

    Principles of good class design

    Member function categories

    Member functions will fall into two primary categories: While there are many forms of these functions: Examples of all these things can be found in the following class declaration examples: Sample calls by the user, using the Circle class above:
      Circle c1, c2;		// build two Circle objects
    
      c1.SetRadius(10);		// set c1's radius
      c2.SetRadius(20);		// set c2's radius
      c1.SetCenter(100,200);	// set c1's center
      c1.Draw();			// draw the first circle
      cout << c1.GetArea();		// retrieve and print the area of c1
    

    Constructors:

    Even with the above design principles, there is one remaining issue. What happens if the user calls upon accessors before they call upon the Set functions, for example? Rather than leave objects uninitialized, we need some way to guarantee initialization that is not left up to the user! (Otherwise, we cannot guarantee that the object is "always in a valid semantic state). There is a special function for this.

    A constructor is a special member function of a class whose purpose is typically to initialize the member data of an object, thus setting it to a valid semantic state immediately upon creation.

    A constructor is easy to recognize because:

  • It has the same name as the class
  • It has no return type
  • Example: Circle class with constructor

    A constructor is a function, and you can define it to do anything you want.  However, you do not explicitly call the constructor function.  It is automatically called when you declare an object.  Example:  

      Circle c1;		// builds object and runs constructor (with no params)
    			//    constructor with 0 parameters is known as a 
    			//    "default constructor"
    
    So how do we use the constructor with the parameter? Example:
      Circle c2(51.4);	// builds object and runs constructor with one 
    			//  param, passing in 51.4 as the parameter value
    
    Watch out for this common mistake, however!
      Circle c3();		// this does NOT build an object.  What is this
    			//  a declaration of?
    

    Example: Fraction Class

    You will find a simple fraction class and driver program in the examples directory -- Click Here
     
  • frac.h contains the class declaration.   (the Declare stage)
  • frac.cpp contains the class definition.  (the Define stage)
  • main.cpp contains a simple driver program that tests the class.  (the Use stage)
  • Note the syntax in the frac.cpp file for defining functions.

      void Fraction::Show() 
      { 
            cout << numerator << '/' << denominator; 
      } 
    

    The declaration for this function in the class header was:

       void Show();
    

    When we write the function definition outside of the class declaration block (as we are doing here, in the file frac.cpp), we must refer back to the class that the function was declared in.  This is the reason for the class name Fraction in the function definition header:

       void Fraction::Show()
    

    The double colon :: is called the scope resolution operator, and it is used for specifying which class a member belongs to when we define it separately from its declaration inside the class.  The format for it's use is:

       className::memberName
    

    Also note the syntax used in calling member functions of an object from the main program file.  We have declared fraction objects:

       Fraction f1, f2;
    

    To call a member function of an existing object, we use the dot-operator.  The syntax format is:

       objectName.memberName
    

    memberName can be a member function call or a member data item

    Examples:

       f1.Show();               // f1 is the object, Show() is the member function 
       cout << f2.Evaluate();   // f2 is the object, Evaluate() is the member function 
    

    Constructor with parameters:

    This fraction example contains the two following constructors:
       Fraction();                        // default constructor 
       Fraction(int n, int d = 1);        // constructor with parameters 
    

    The term default constructor will always refer to a constructor with no parameters.  When we declared objects in the simple fraction example, its default constructor was used because no parameters were passed.  Example:

       Fraction f1, f2;    // f1 and f2 are now Fraction objects 
    

    To utilize a constructor with parameters, we can pass arguments in when the object is declared. Examples:

       Fraction f1(2,3);    // passes 2 and 3 as the parameters (2/3) 
    
       int x = 4, y = 8; 
       Fraction f2(x,y);    // passes in the values stored in x and y 
    

    Notice, also, that this constructor has a default value on the second parameter, which makes it an optional parameter.  If only one argument is passed in, the second parameter takes the default value, 1.

       Fraction f3(6);    // initializes a fraction to 6/1 
    

    Here's a revised copy of the Fraction class -- error checking added in