Advanced OOP using C++

Constructors and Destructors

Published:  August 6, 2008
By Richard G. Baldwin

File:  AdvCpp00135


 

Preface

General

The purpose of this series of tutorial lessons is to help you progress from procedural programming using C++ to object-oriented programming (OOP) using C++.  As I have mentioned in earlier lessons (see Resources), most of the code in these lessons is being written in such a way as to make it compatible with the display of output data on the command-line screen using Dev-C++.  However, you can easily modify the code to make it compatible with other C++ programming tools.

This lesson presents and explains two different programs that illustrate the behavior of constructors and destructors.

Viewing tip

I recommend that you open another copy of this document in a separate browser window and use the following links to easily find and view the figures and listings while you are reading about them.

Figures

Listings

Supplementary material

I recommend that you also study the other lessons in my extensive collection of online programming tutorials.  You will find a consolidated index at www.DickBaldwin.com.

General background information

When you create a class in C++, you are, in effect, creating a new data type. Having created the new type, you can declare instances of the type in the form of variables commonly called objects. In addition to data stored in the object, the class can also define member functions which provide the means for manipulating the data stored in the object. These member functions provide the interface between the encapsulated data in the object and the other parts of the program.

Constructors and destructors

Specially formatted member functions can also be provided that execute automatically when an object is created and destroyed.  The special functions that execute automatically when the object is created are commonly called constructors.  Constructors were invented for the express purpose of initializing the object's data to specified values when the object is created.

The special functions in the latter category are commonly called destructors.  The purpose of destructors is to eliminate the data when it is no longer needed.

A common use for destructors is to free dynamically-allocated memory at such time as the data that occupies that memory is no longer needed.  (Dynamically allocated memory will be the topic of future lessons.)  The failure to properly free dynamically-allocated memory when appropriate leads to a fairly common form of program failure, which is often referred to as a memory leak.

Overloading

With the exception of destructors, the member functions in a class can be overloaded to perform different actions whenever the type or number (or both) of the arguments differs from one call to the next. Constructors are no exception to this rule. It is common practice to use overloaded constructors that initialize the data in different ways, depending on how an object is specified when it is declared. These are sometimes referred to as parameterized constructors.

Preview

A class definition in C++ creates a new data type from which you can create instances (objects).  The object can contain data, member functions, multiple overloaded constructors, and a single destructor.

Constructors should be used to initialize the values of the data items contained in the object.  The destructor should be used to dispose of those data items in an orderly way when the data is no longer needed, making certain to avoid memory leaks.

This lesson presents and explains two different programs that illustrate the behavior of constructors and destructors.

Constructors and destructors

A C++ class may have multiple overloaded constructors and a single destructor.

Constructors

It is very common for parts of your program to require initialization. When working with real problems, virtually every object that you create will probably require some sort of initialization.  C++ does not generally provide default initialization values.  The failure to properly initialize variables and objects in C++ leads to a fairly common form of runtime program failure resulting from the processing of left-over garbage in memory as though it is valid data.

To address this situation, C++ allows a constructor to be included in a class declaration. The constructor for a class is called each time an object of that class is created. Thus, any initialization that needs to be performed on an object can be performed by the code in the constructor when the constructor is automatically executed.

A constructor has the same name as the class of which it is a part and has no return type. The example program in Listing 6 illustrates the behavior of a constructor.

Will explain in fragments

I will explain this program in fragments.  The fragment in Listing 1 shows the beginning of the program and the class declaration.

Listing 1. Class declaration for the program named Prog135A.
#include <iostream>
using namespace std;

class MyClass{
  int var;  //private variable
public:
  MyClass();  //constructor
  void show();//display the value of the variable "var"
}; //end of class declaration

The constructor declaration is highlighted in blue boldface. Note that the name of the constructor is the same as the name of the class and that it does not specify a return type.

In this case, the constructor doesn't require any incoming parameters.  However, there could be multiple overloaded constructors each one requiring different numbers and/or types of parameters.

Definition of the constructor and the show function

Listing 2 shows the definition of the constructor and the function named show.  The constructor is highlighted in blue boldface.  Note that the constructor must be public for the program to compile because it is called from outside the class.

Listing 2. Definition of the constructor and the show function.
MyClass::MyClass(){  //define the constructor
  cout << "  In the constructor setting var to 10\n";
  var = 10;  //set var to a value of 10
}//end constructor definition

void MyClass::show(){ //define the show function
  cout << "  In the show function, var = " << var << "\n";
}//end show function

In this example, the value of the private data member var is initialized to a value of 10 by code in the constructor named MyClass. The constructor is called when the object named obj is created by the code in the main function (see Listing 3). An object is created when that object's declaration statement is executed.

The main function

The main function in the program named Prog135A is shown in Listing 3.

Listing 3. The main function in the program named Prog135A.
int main(){
  cout << 
        "Create the object and execute the constructor\n";
  MyClass obj;

  cout << "Execute the show function\n";
  obj.show();

  //return 0;
  //Following statements cause Dev-C++ output to remain
  // on the screen
  system("PAUSE");
  return EXIT_SUCCESS;
}// end main

Construct the object

The main function begins by declaring an object named obj of the class named MyClass.  This is the point in time when the constructor code shown in Listing 2 is executed causing a value of 10 to be stored in the private member variable named var that belongs to the new object.  The main function also causes some text to appear on the command-line screen.

Display the contents of the object

Then the main function calls the public show method, which is defined in Listing 2, and which belongs to the object.  The code in the show method displays the current value stored in the variable named var belonging to the object on which the function is called.  The value of var is displayed on the command-line screen, producing the screen output shown in Figure 1 when the program is compiled and executed using Dev-C++.

Figure 1. Screen output from the program named Prog135A
Create the object and execute the constructor
  In the constructor setting var to 10
Execute the show function
  In the show function, var = 10
Press any key to continue . . .

Destructors

As the name implies, a destructor has a behavior that is the opposite of a constructor.  While a constructor builds an object up, a destructor tears it down.

The destructor is called when the object to which it belongs is destroyed.  This can happen in a variety of ways, but it usually means that either the object has gone out of scope, or the program code has purposely destroyed the object.

Cleanup code is frequently needed

When working with objects, it is very common to have to perform some actions when an object is destroyed. For example, an object that allocates memory when it is created will need to free that memory when it is destroyed. Otherwise, the program will exhibit a characteristic commonly referred to as a memory leak.

The destructor's name

Like a constructor, the name of a destructor must match the name of the class to which it belongs, with the following exception.  You include a destructor in a class declaration by preceding the name with a tilde (~).  A destructor never receives any parameters and can't be overloaded.

Destruction of an object

Local objects are destroyed when they go out of scope. Global objects are destroyed when the program ends. Dynamically allocated objects are destroyed when the program purposely destroys them, or when the program ends.

A sample program with a destructor

The sample program that is presented in Listing 7 adds a destructor to the previous program and demonstrates that the destructor is called when the program ends.

Class declaration for the program named Prob135B

As before, I will discuss and explain this program in fragments.  The class declaration for the program is shown in its entirety in Listing 4.

Listing 4. Class declaration for the program named Prob135B.
#include <iostream>
using namespace std;

class MyClass{
  int var;  //private variable
public:
  MyClass();  //constructor
  ~MyClass(); //destructor
  void show();//display the value of the variable "var"
}; //end of class declaration

The only thing that is new in Listing 4, as compared to Listing 1 is the declaration of the destructor, which is highlighted in blue boldface in Listing 4.  Note the tilde in the syntax for the destructor.  Also note that the destructor doesn't receive any parameters.

Definition of constructor, destructor and show function

Listing 5 shows the definition of the constructor, the destructor and the show function.

Listing 5. Definition of constructor, destructor and show function.
MyClass::MyClass(){  //define the constructor
  cout << "  In the constructor setting var to 10\n";
  var = 10;  //set var to a value of 10
}//end constructor definition

MyClass::~MyClass(){//define the destructor,note the tilde
  cout << "  In the destructor...\n";
} //end definition of destructor

void MyClass::show(){ //define the show function
  cout << "  In the show function, var = " << var << "\n";
}//end show function

The only thing that is new in Listing 5 relative to Listing 2 is the definition of the destructor, which is highlighted in blue boldface in Listing 5.

The destructor doesn't have anything important to do in this simple program.  It displays a message on the command-line screen to demonstrate that it is executed when the main function terminates causing the object to go out of scope and to be destroyed.

The main function

The main function in this program is identical to that shown in Listing 3, so I won't discuss it further.

The screen output

The screen output from running this program is shown in Figure 2.

Figure 2. Screen output from the program named Prog135B.
Create the object and execute the constructor
  In the constructor setting var to 10
Execute the show function
  In the show function, var = 10
Press any key to continue . . .
  In the destructor...  

A little trickiness here

Note that viewing the screen output produced by the destructor (shown in blue boldface in Figure 2) is a little tricky.  If you include the special Dev-C++ code shown at the end of Listing 3 and execute the program from within Dev-C++, you won't see the output produced by the destructor.  This is because the line of text that reads "Press any key to continue . . ."  and the pause that follows the display of that text is produced by the special Dev-C++ code at the end of Listing 3.

In effect, this special code causes the execution of the program to pause so that you can view the output before the main function returns and the function terminates.  However, the destructor isn't executed until the main function returns causing the object to go out of scope and to be destroyed.  When you press a key as instructed, the output screen disappears immediately and you don't see the last line of output that is produced by the destructor.

Must run directly from the command line

You will need to compile this program and then execute it directly from a command line to see the output produced by the destructor.  In this case, you can either leave the special Dev-C++ code in the main method (see Listing 3) and press a key when instructed to do so, or you can replace that code with a simple return statement.  In the latter case you won't be prompted to press a key to continue.  In either case, the output produced by the destructor should be the last thing that you see before control returns to the command-line prompt.

Programming style

Technically, a constructor or a destructor can perform just about any type of operation that is supported by C++ code. The code that occurs within these special functions does not have to initialize or remove anything. However, having a constructor or destructor perform actions not directly related to the initialization or orderly destruction of an object makes for very poor programming style and should be avoided.

Summary

A class definition in C++ creates a new data type from which you can create instances (objects).  The object can contain data, member functions, multiple overloaded constructors, and a single destructor.

Constructors should be used to initialize the values of the data items contained in the object.  The destructor should be used to dispose of those data items in an orderly way, making certain to avoid memory leaks.

This lesson presented and explained two different programs that illustrate the behavior of constructors and destructors.

Complete program listings

Complete listings of the programs discussed in this lesson are shown in Listing 6 and Listing 7 below.

Listing 6. Source code for the program named Prog135A.
//File Prog135A
/*********************************************************
Constructors
This program illustrates the behavior of a constructor.
*********************************************************/

#include <iostream>
using namespace std;

class MyClass{
  int var;  //private variable
public:
  MyClass();  //constructor
  void show();//display the value of the variable "var"
}; //end of class declaration

MyClass::MyClass(){  //define the constructor
  cout << "  In the constructor setting var to 10\n";
  var = 10;  //set var to a value of 10
}//end constructor definition

void MyClass::show(){ //define the show function
  cout << "  In the show function, var = " << var << "\n";
}//end show function

//Test the class
int main(){
  cout << 
        "Create the object and execute the constructor\n";
  MyClass obj;

  cout << "Execute the show function\n";
  obj.show();

  //return 0;
  //Following statements cause Dev-C++ output to remain
  // on the screen
  system("PAUSE");
  return EXIT_SUCCESS;
}// end main

 

Listing 7. Source code for the program named Prog135B.
//File Prog135B
/*********************************************************
Constructors
This program illustrates the behavior of a destructor.
*********************************************************/

#include <iostream>
using namespace std;

class MyClass{
  int var;  //private variable
public:
  MyClass();  //constructor
  ~MyClass(); //destructor
  void show();//display the value of the variable "var"
}; //end of class declaration

MyClass::MyClass(){  //define the constructor
  cout << "  In the constructor setting var to 10\n";
  var = 10;  //set var to a value of 10
}//end constructor definition

MyClass::~MyClass(){//define the destructor,note the tilde
  cout << "  In the destructor...\n";
} //end definition of destructor

void MyClass::show(){ //define the show function
  cout << "  In the show function, var = " << var << "\n";
}//end show function

//Test the class
int main(){
  cout << 
        "Create the object and execute the constructor\n";
  MyClass obj;

  cout << "Execute the show function\n";
  obj.show();

  //return 0;//cause the object to go out of scope
  //Following statements cause Dev-C++ output to remain
  // on the screen.
  system("PAUSE");
  return EXIT_SUCCESS;
}// end main

 

Resources


Copyright

Copyright 2008, Richard G. Baldwin.  Reproduction in whole or in part in any form or medium without express written permission from Richard Baldwin is prohibited.

About the author

Richard Baldwin is a college professor (at Austin Community College in Austin, TX) and private consultant whose primary focus is a combination of Java, C#, and XML. In addition to the many platform and/or language independent benefits of Java and C# applications, he believes that a combination of Java, C#, and XML will become the primary driving force in the delivery of structured information on the Web.

Richard has participated in numerous consulting projects and he frequently provides onsite training at the high-tech companies located in and around Austin, Texas.  He is the author of Baldwin's Programming Tutorials, which have gained a worldwide following among experienced and aspiring programmers. He has also published articles in JavaPro magazine.

In addition to his programming expertise, Richard has many years of practical experience in Digital Signal Processing (DSP).  His first job after he earned his Bachelor's degree was doing DSP in the Seismic Research Department of Texas Instruments.  (TI is still a world leader in DSP.)  In the following years, he applied his programming and DSP expertise to other interesting areas including sonar and underwater acoustics.

Richard holds an MSEE degree from Southern Methodist University and has many years of experience in the application of computer technology to real-world problems.

Baldwin@DickBaldwin.com

-end-