Class concepts (details)

Objectives

  • Implement constructors
  • Implement destructors
  • Implement dynamic memory allocation
  • Compare and contrast inheritance and composition
  • Define the terms: encapsulation, inheritance, and polymorphism
  • Discuss the importance of encapsulation, inheritance, and polymorphism
  • Implement C++ classes
  • Write and use overloaded functions
  • Use initialization lists

Terminology

  • Inheritance: using an existing class/object to create a new class object; all of the data and methods from the base class (superclass) are inherited by the derived class (subclass)
  • Instance: an object is called an instance of the class it is based on
  • Instantiation: creating an object from a class
  • Composition: using an object as a data member of another object
  • Inheritance specifies an "is-a" relationship
  • Composition specifies a "has-a" relationship
  • A C++ class can inherit from multiple classes; this can be quite confusing and will be avoided in this course

A simple class

  • Class definition format: class className: memberAccessSpecifier baseClassName { memberList };
  • See Point.cpp
  • private: accessible only within same class
  • public: accessible to any code
  • protected: accessible only within same class and derived classes (subclasses)
  • Constructors: used to initialize instance variables and allocate initial resources
  • Default constructor: the constructor that has no arguments
  • Converging constructors through a common initialization function so all initialization code is in one spot
  • Constructors may have initialization lists; they are specified in the function header and separated using a colon after the parameter list
  • Initialization lists can be used to specify which base class constructor to call and which arguments to send it
  • Accessor (get) methods: used by other classes to get the value of private variables
  • Mutator (set) methods: used by other classes to change the value of private variables
  • Predicate methods are those that return true or false
  • const modifier (before parameter): means that the parameter may not be changed within the function
  • const modifier (at end of function head): means that the function may not change the value of its static or instance variables
  • Converging code through one validation routine is encouraged to make troubleshooting and modification easier
  • new and delete: operators used to create and destroy objects
  • Regular object variables vs. pointers
  • Accessing members of objects through reference variables: use . (dot, member of) operator
  • Accessing members of objects through pointers: use -> operator
  • A base class data member with an identifier name duplicated in the derived class can be called using the scope resolution operator as follows: ::identifier

Function return types

  • Easy to return a single built-in type
  • Easy to return an object
  • Problems arise when returning local (automatic variables) and dynamically allocated memory
  • Local variables don't exist after return statement
  • Dynamically allocated memory must eventually be released
  • Traditional C-style strings can be a big problem

Function overloading

You can have multiple functions with the same name, but different argument lists. The compiler can determine which function to use based on the argument list.

See overload1.cpp for an example.

Constructors, destructors, and dynamic memory allocation

It is common to overload constructors, but unlike Java, C++ constructors can not call each other. Since we try to eliminate duplicate code when possible and funnel error checking through individual functions for each check, it makes sense to create a common initialization function that all the constructors can call. This initialization function is also the ideal place to update a static object count variable if there is one.

You don't have to worry about overloading destructors. There can be only one. A destructor may not be needed unless you have to deallocate memory that was allocated by the object in a constructor or mutator method. Another reason you might need a destructor is to decrement a static object count variable.

The examples for this section use a C-style string as an instance variable. Smooth handling of a C-style string instance variable usually requires dynamic memory allocation and deallocation. You have to be careful when writing such code so you know that the pointer to the string has been initialized properly, and the memory returned when the object is destroyed.

See person.h, person.cpp, and testPerson.cpp for an example.

See person2.h, person2.cpp, and testPerson2.cpp for a more detailed example using dynamic memory allocation.

Example programs

  • class1.cpp: basic complex class structure, uses C-style fixed length string
  • class2.cpp: basic complex class structure, uses C++ string object
  • class3.cpp: basic complex class structure, uses C-style string with dynamic memory allocation