Stock second(); // declares a function
Stock third; // calls default constructor
The first declaration here calls the nondefault constructor—that is, the one that takes arguments. The second declaration states that second() is a function that returns a Stock object. When you implicitly call the default constructor, you don’t use parentheses.
Destructors
When you use a constructor to create an object, the program undertakes the responsibility of tracking that object until it expires. At that time, the program automatically calls a special member function bearing the formidable title
Like a constructor, a destructor has a special name: It is formed from the class name preceded by a tilde (~). Thus, the destructor for the Stock class is called ~Stock(). Also like a constructor, a destructor can have no return value and has no declared type. Unlike a constructor, a destructor must have no arguments. Thus, the prototype for a Stock destructor must be this:
~Stock();
Because a Stock destructor has no vital duties, you can code it as a do-nothing function:
Stock::~Stock()
{
}
However, just so that you can see when the destructor is called, let’s code it this way:
Stock::~Stock() // class destructor
{
cout << "Bye, " << company << "!\n";
}
When should a destructor be called? The compiler handles this decision; normally your code shouldn’t explicitly call a destructor. (See the section “Looking Again at Placement new” in Chapter 12, “Classes and Dynamic Memory Allocation,” for an exception.) If you create a static storage class object, its destructor is called automatically when the program terminates. If you create an automatic storage class object, as the examples have been doing, its destructor is called automatically when the program exits the block of code in which the object is defined. If the object is created by using new, it resides in heap memory, or the free store, and its destructor is called automatically when you use delete to free the memory. Finally, a program can create temporary objects to carry out certain operations; in that case, the program automatically calls the destructor for the object when it has finished using it.
Because a destructor is called automatically when a class object expires, there ought to be a destructor. If you don’t provide one, the compiler implicitly declares a default constructor and, if it detects code that leads to the destruction of an object, it provides a definition for the destructor.
Improving the Stock Class
At this point we need to incorporate the constructors and the destructor into the class and method definitions. Given the significance of adding constructors, we’ll advance the name from stock00.h to stock10.h. The class methods go into a file called stock10.cpp. Finally, we place the program using these resources in a third file, usestok2.cpp.
The Header File
Listing 10.4 shows the header file for the stock program. It adds prototypes for the constructor and destructor functions to the original class declaration. Also it dispenses with the acquire() function, which is no longer necessary now that the class has constructors. The file also uses the #ifndef technique described in Chapter 9 to protect against multiple inclusion of this file.
Listing 10.4. stock10.h
// stock10.h -- Stock class declaration with constructors, destructor added
#ifndef STOCK10_H_
#define STOCK01_H_
#include
class Stock
{
private:
std::string company;
long shares;
double share_val;
double total_val;
void set_tot() { total_val = shares * share_val; }
public:
// two constructors
Stock(); // default constructor
Stock(const std::string & co, long n = 0, double pr = 0.0);
~Stock(); // noisy destructor
void buy(long num, double price);
void sell(long num, double price);
void update(double price);
void show();
};
#endif
The Implementation File