Professional Documents
Culture Documents
Destructors
Storage Classes
6-1
Destructors
The purpose of a constructor was to perform initial processes such as initializing
variables, opening files etc. Just as there are things that need to take place when an
object is instantiated, there are often things we need to take care of when an object ceases
to exist. A destructor is a special member function of a class that is used for resource
deallocation. The name of the destructor for a class is the class name preceded by a tilde
(~). A class' destructor is called when an object is destroyed - for automatic variables,
variables created when their block is entered and destroyed when the block is exited, this
would be when program execution leaves the scope in which an object was instantiated.
The destructor is run automatically at this time. Objects that were dynamically allocated
are not automatically destroyed when they go out of scope. These objects are destroyed
only by using the _____________________________________ on the pointer. If this is
not done, a ______________________________ will result. To further compound the
situation, any resources inside the object will also remain unreleased. Simply put, the
destructor is not run when a __________________________________________ an
object goes out of scope. The destructor is run only when a pointer to a dynamically
allocated object is deleted or when an actual object (not a reference to that object) goes
out of scope. Explicit destructors are required only when there are resources to be
relinquished. Destructors are not limited to giving back resources, they can perform any
task the class designer wishes them to perform when an object is destroyed.
- A destructor receives no parameters and returns no value.
- A class may have only one destructor - destructor overloading is not allowed
- Fully implemented destructors are appropriate for classes whose objects contain
dynamically allocated memory.
- Every class should contain a destructor even if the destructor does nothing.
- Unlike constructors, even if you include a destructor in your class, the compiler
will still supply and run its own synthesized destructor. It destroys each
nonstatic member in the reverse order from which it was declared. Example:
class Employee
{
public:
Employee( );
~Employee( );
private:
string empName;
};
Employee::~Employee( )
{
}
Even though the Employee destructor does nothing, the synthesized destructor will
run and call the destructor supplied by the string class to destroy empName. The
synthesized destructor does nothing to built in types.
6-2
Storage Classes
An identifier's storage class determines the period of time in which an identifier exists in
memory. Some identifiers exist for a short period of time, some are created and
destroyed repeatedly, and others exist during the entire execution of the program. An
identifiers scope is where the identifier can be referenced in a program. Some exist
throughout the program while others can be referenced from only limited portions of the
program. The storage class identifiers can be split into two storage classes: automatic
storage class and static storage class. Note: Using multiple storage class identifiers in a
declaration produces a compiler error.
6-3
register - Used to suggest to the compiler that it maintain the variable in one of the
computer's high-speed hardware registers rather than in memory. If variables
that are used extensively in a program such as counters and totals can be
maintained in hardware registers rather than in memory, this cuts down on
the overhead of repeatedly loading the variables from memory into the
registers and then storing the results back into memory. As there are only
a certain number of hardware registers available, the compiler might choose
to ignore your suggestion. Note also that many compilers today are very
good at optimizing code and can decide which variables would be better
stored in a register.
register int count = 1;
The keyword register may be used with local variables and function
parameters only.
6-4
extern - Global variables and function names by default are storage class extern.
When a variable declaration is placed outside of any block in the program,
this variable becomes global and their values exist throughout the entire
program execution cycle. These variables can be referenced by any
function that follows their declaration Likewise for function declarations.
static -
When local variables are declared with the keyword static, their values are
retained even when the function has ceased execution. These variables are
still accessible only within the block in which they were defined but their
old value is available the next time the function is called. Any numeric
variable of static storage class is initialized to zero if it is not done explicitly
by the programmer.
static int count = 1;
class C
{
public:
C();
~C();
};
class A
{
public:
A();
~A();
private:
C aVar;
};
class B : public A
{
public:
B();
~B();
private:
C bVar;
};
void someFunc();
int main()
{
someFunc();
B bVal;
return 0;
}
void someFunc()
{
static C funcVal;
}
C::C(){ cout << "create C\n"; }
C::~C(){ cout << "destruct C\n"; }
A::A(){ cout << "create A\n"; }
A::~A(){ cout << "destruct A\n"; }
B::B(){ cout << "create B\n"; }
B::~B(){ cout << "destruct B\n"; }
6-6
class CreateAndDestroy
{
public:
CreateAndDestroy(int val);
~CreateAndDestroy();
private:
int privateVal;
};
void Create(void);
CreateAndDestroy first(1);
int main()
{
cout << "\t(global object before main)\n";
CreateAndDestroy second(2);
cout << "\t(local automatic in main)\n";
static CreateAndDestroy third(3);
cout << "\t(local automatic in main)\n";
Create();
CreateAndDestroy fourth(4);
cout << "\t(local automtic in main)\n";
return 0;
}
CreateAndDestroy::CreateAndDestroy(int val)
{
privateVal = val;
cout << "Construct object " << privateVal;
}
CreateAndDestroy::~CreateAndDestroy()
{
cout << "Destruct object " << privateVal << endl;
}
void Create(void)
{
CreateAndDestroy fifth(5);
cout << "\t(local automatic in create)\n";
static CreateAndDestroy sixth(6);
cout << "\t(local static in create)\n";
CreateAndDestroy seventh(7);
cout << "\t(local automatic in create)\n";
}
Show the output from this program.
6-7
Destructor Exercise
struct StringRec
{
char theCh;
StringRec* nextCh;
};
typedef StringRec* StrPtr;
class String
{
public:
String();
~String();
void SetString();
void OutputString();
int GetLength()const;
protected:
StrPtr head;
int strLength;
};
class StringModifier : public String
{
public:
StringModifier();
~StringModifier();
//Assumes the head of the string is not null and the string contains at least n characters
void InsertAfter(StringModifier& subStr, int n);
};
Implement the following functions:
String::String()
{
}
// destructor deletes the list elements and releases the memory
String::~String()
{
6-8
// read from buffer one character at a time and build the list
void String::SetString()
{
StrPtr p,last;
char tempCh;
last = head;
cout << "Enter a string: ";
cin.get(tempCh);
while(tempCh != '\n')
{
}
}
//Assumes the head of the string is not null and the string contains at least n characters
void StringModifier::InsertAfter(StringModifier& subStr, int n)
{
StrPtr p,q,r;
6-9
Name _____________________________________________
Due Date __________________
String Function Homework
Use the code from the string function exercise done in class. Using the class String and the class
StringModifier, add a member function to StringModifier called FindSubString.
The FindSubString function returns an integer representing the position of the start of the
requested sub-string, or -1 if the sub-string is not found. The first character is located at position
0. The search for the sub-string begins at "index" n.
Example 1
"Mother is at her best in her home."
Find sub-string "her" starting at position 0.
Found starting at position 3
Found starting at position 13
Found starting at position 25
There are 3 occurrences of "her" in the string.
Example 2
"Help me!"
Find sub-string "elp" starting at position 2.
No occurrences were found.
6-10