CIS322 Object Oriented Programming: Advanced C++


<< back to courseware demo page
- This online lecture is for demonstration purposes

 

Lecture Two

Classes and Data Abstraction

Each Student will have reading assignment for this lecture.

The menu to the right provides links to the major topics of the lecture as well as to the assignment page for this lecture. You may also scroll down to begin reading the lecture material.

What you need to know

A class is a derived type whose elements are other types.  Unlike an array, the elements of a class may have different types.  Furthermore, elements of a class may be functions, including operators.

Although any region of storage may generally be regarded as an "object," the word is usually used to described variables whose type is a class.  Thus, "object-oriented programming" involves programs that use classes.  An object can be conceived as a self-contained entity that stores its own data and owns its own functions.  The functionality of an object gives it life in the sense that it "knows" how to perform tasks on its own.

 

Lecture Menu

Objectives

Class and Access Specifiers

Constructor and Destructor

Summary

Review Questions

Practice Test

Required Readings

 

Learning Objectives

After completing Lecture Two, you will be proficient in key aspects of this competency expectation include: 

  • Understanding the software engineering concepts of encapsulation and data hiding.
  • Understanding how to create, use, and destroy class objects.
  • Understanding how to control access to object data members and member functions.
  • Class and Access Specifiers (Public/Private)

    A key feature of OOP is information (data) hiding, and the purpose is to prevent information from being accidentally accessed by functions that don’t need to access it.  In C++, information hiding is achieved by putting data in a class and declaring it private.  Private data or member functions can only be accessed from within the class where they are defined.  On the other hand, data or member functions declared public are accessible from outside the class where they are defined.

    Generally, the data in a class is declared private and functions public.  However, in some cases, one might want to make data public and functions private.

    Here is an example of the declaration of a class called Account:

     

    // declaration of class Account
    class Account
    {
        private:
           char*    name;      // name of the acct holder
           char*    acctNum;   // account number
           double  bal;        // account balance

        public:
           void setName(const char*);      // set the value of name
           void setAcctNum(const char*);   // set the value of acctNum
           void setBalance(const double);  // set the value of bal

           void deposit(const double);
           bool withdraw(const double);

           // other member functions …
    };

    // implementation of function setName()
    void Account::setName(const char* aName)
    {
       name = new char[strlen(aName) + 1]; // allocate memory for name
       strcpy(name, aName);
    }

    // implementation of function setAcctNum()
    void Account::setAcctNum(const char* aAcctNum)
    {
       acctNum = new char[strlen(aAcctNum)+1]; // allocate memory for acctNum
       strcpy(acctNum, aAcctNum);
    }

    // implementation of function setBalance()
    void Account::setBalance(const double aBalance)
    {
       bal = aBalance;
    }

    // implementation of function deposit()
    void Account::deposit(const double aDeposit)
    {
       bal += aDeposit;
    }

    // implementation of function withdraw()
    // return value: true – withdraw successful; false - otherwise
    bool Account::withdraw(const double aWithdraw)
    {
       if(bal >= aWithdraw)   // sufficient fund to cover the withdraw
       {
           bal -= aDeposit;
           return true;
       }
       else                   // not enough fund to cover the withdraw
         return false;
    }

    Note, const is a keyword, which specifies that the value of a variable or parameter is not allowed to be changed, and the variable or parameter is called constant.  Constants have two entities involved when pointers are used: the pointer and the object pointed to.  Either, or both, can be constant:

    char a=‘a’, b=‘b’;

    const char* pcc = &a;   // pointer to const char
    pcc = &b;               // ok
    *pcc = ‘Z’;             // error

    char* const cpc = &a;   // const pointer to char
    cpc = &b;               // error
    *cpc = ‘Z’;             // ok

    const char* const cpcc = &a;  // const ptr to const char
    cpcc = &b;                    // error
    *cpcc = ‘Z’;                  // error
    pcc = cpc;              // ok
    pcc = cpcc              // ok

    A member function could also be declared as const by the keyword const suffix to the argument list, which specifies that the member function be not allowed to change values of data members of the class for which the function is called.  For example,

    class X
    {
         int i;
         // …

       public:
         void setI(int i);
         void print() const;  // this function will not change the value of i
         // …
    };

    Note, non-const functions can’t be called for const objects, and const member functions can be called for both const & non-const objects:

    const X x0;
    x0.setI(5);   // error
    x0.print();

    X x1;
    x1.setI(5);
    x1.print();   // ok

    Back to the Account example, to use the Account class, one could do the following:

    Account  acct;                // create an instance of Account
    acct.setName(“John”);         // initialize acct’s  name
    acct.setAcctNum(“012345”);    // initialize acct’s  acctNum
    acct.setbalance(500.86);      // initialize acct’s  bal
     

    Constructor and Destructor

    A constructor is a member function that has the same name as its class, and does not have return type.  Multiple constructors can be defined for each class.  If no constructor is defined for a class, the compiler will generate a default constructor, which is really an empty constructor and consequently does nothing.   Whenever an object of a class is created, the compiler will implicitly call a constructor for that class.

    To illustrate with the previous Account class example:

    // declaration of class Account
    class Account
    {
        private:
           char*  name;       // name of the acct holder
           char*  acctNum;    // account number
           double  bal;       // account balance

        public:
           // constructor
           Account(char* name, char* acctNum, double bal); 

           void setName(char*);      // set the value of name
           void setAcctNum(char*);   // set the value of acctNum
           void setBalance(double);  // set the value of bal

           void deposit(double);
           bool withdraw(double);

           // other member functions …
    };

    // implementation of Account constructor
    Account::Account(char* aName, char* aAcctNum, double aBalance)
    {
       setName(aName);
       setAcctNum(aAcctNum);
       setBalance(aBalance);
    }

    In the above example, Account constructor takes three arguments to initialize the three data members - name, acctName and bal.

    Now, one could create and utilize an instance of Account as follows:

    /* create an Account object, and initialize it with the three passed ** parameters
    */
    Account  acct(“John”, “012345”, 500.86); 
    acct.withdraw(200);  // withdraw money from the account
    acct.deposit(300);   // deposit money into the account

    Here one does not have to call the three set member functions to initialize the data members, the compiler automatically executes the constructor upon the instantiation of the object acct, and in this particular implementation, the constructor in turn calls the three set functions to do the initialization.

    A constructor is called each time an object is created, and C++ also supports a mechanism complementary to constructors for the automatic cleanup of objects – a special member function called destructor is invoked automatically by the compiler whenever an object is destroyed (e.g., by going out of scope or by using the “delete” operator).

    A destructor has the same name as its class but is preceded by a “~” (tilde).  It takes no argument and has no return type.  In addition, there can be only one destructor for each class.  The purpose of a destructor is to do cleanup (e.g., release memory).

    To continue with the Account class example, one might define the Account class as follows:

    // declaration of class Account
    class Account
    {
        private:
           char*   name;      // name of the acct holder
           char*   acctNum;   // account number
           double  bal;       // account balance

        public:
           // constructor
           Account(char* name, char* acctNum, double bal); 
           // destructor
           ~Account(); 

           void setName(char*);      // set the value of name
           void setAcctNum(char*);   // set the value of acctNum
           void setBalance(double);  // set the value of bal

           void deposit(double);
           bool withdraw(double);

           // other member functions …
    };

    // implementation of Account destructor
    Account::~Account()
    {
       delete[] name;      // release memory allocated for name
       delete[] acctNum;   // release memory allocated for acctNum
    }

    The “delete” in the above destructor is a key word in C++, and its semantics is to de-allocate memory previous allocated with a “new” statement.  We shall take more about the “new” and “delete” in the next lecture.
     

    Summary

    C++ supports the information hiding through the mechanism of class and access specifiers. 
    Data (information) is concealed in a class, and access specifiers protect data integrity from unintentional access by programmer’s honest mistakes. Constructor/destructor provides a systematic way to initialize and clean up objects.

    1. Classes enable the programmer to model objects with attributes and behaviors.  Class types can be defined in C++ using the keywords class and struct.  But class is normally used for this purpose.

    2. Any data member or member function declared after public: in a class is visible to any function with access to an object of the class.

    3. Private data are not accessible from outside the class.

    4. A constructor is a special member function with the same name as the class that is used to initialize the members of a class object.  The constructor is called when an object of that class is instantiated.

    5. The function with the same name as the class but proceeded with a tilde character (~) is called a destructor.

    6. The set of public member functions of a class is called the class’ interface.

    7. Member functions defined in a class declaration are automatically inlined.

    8. Member selection operators . and -> are used to access class members.

    9. A fundamental principle of good software engineering is to expose interface but hide the implementation.

    10. Access to a class’ private data can be carefully controlled via member functions called access functions.  If a class wants to allow clients to read private data, the class can provide a get function.  To enable clients to modify private data, the class can provide a set function.

    11. Data members of a class are normally made private and member functions of a class are normally made public.  Some member functions may be private and serve as utility functions to the other functions of the class.

    12. Constructors can be overloaded.

    13. When an object of a class is defined, initializers can be provided.  These initializers are passed to the class’ constructor.

    14. Constructors do not return values

    15. The destructor of an automatic object is called when the object goes out scope.  The destructor should be implemented to perform cleanup.

    16. Destructors do not receive parameters nor return values.  A class can have only one destructor (destructors cannot be overloaded).

    17. The new operator allocates space for an object, runs the object’s constructor and returns a pointer of the correct type.

    18. The delete operator deallocates space for an object.

    19. An array of objects can be allocated dynamically with new as in

             int* ptr = new int[100];

    which allocates an array of 100 integers and assigns the starting location of the array to ptr.  To     delete the array, use the following statement

           delete[] ptr;
     

    Review Questions
     

    1. Write a statement that executes the getAcctNum() function in the Bank class, as described in question 3 and 4.
     

    2. Write a constructor that initializes the acctNum to NULL for the Bank class described in questin 3.
     

    3. The dot operator(or class member access operator) connects the following two entities(reading from left to right):
    a. a class member and a class object
    b. an object and a class
    c. a class and a member of that class
    d. an object and a member of that class
     

    4. A constructor is executed automatically when an object is __________________.
     

    5. A constructor’s name is the same as ____________________________________.
     
     

    Answers:

    1. char* accountNumber = bank.getAcctNum().

    2. Bank::Bank()
        {
            acctNum = NULL;
        }

    3. d

    4. defined(created, instantiated)

    5. the class of which it is a member
     

    Practice Test

    1. In a access specifier, data member or member functions declared private are accessible
    a. to any functions in the program
    b. only if you know the password
    c. to member functions of that class
    d. only to public members of the class

    2. Data members in a class must be private.
    a. True
    b. False

    3. Write a declaration of a class called Bank with one private data member, acctNum, of type char*, and one public member function whose prototype is char* getAcctNum().

    4. Write a statement that defines an object called bank of the class Bank described in question 3.

    5. Write a member function called getAcctNum() for the class Bank described in question 3.  This function should return the value of the acctNum data member.
     
     

    Answers:

    1. c

    2. b

    3. class Bank
       {
           char* acctNum;

           public:
           char* getAcctNum();
       };

    4. Bank bank;

    5. char* Bank::getAcctNum()
       {
         return acctNum;
       }
     

    Required Readings

    Textbook: 
                             Classes, access to members (public/private)     (13.1-13.7)
                             Constructors / destructors   (13.9-13.15, 14.4)

    Tony Gaddis 
    Standard Edition of Starting Out with C++ (3rd Edition) 
    Scott/Jones Inc., El Granada CA, 2001. 
    ISBN 1-57676-031-6.