| If function f has
called g, which, in turn, called h, then the stack looks
something like this: |
(introduced in Chptr. 6)
E.g., String class, with underlying array on heap.
class String
{
public:
String(); // Default constructor
String(const char p[]); // Simple constructor
String(const String& right); // Copy constructor
~String(); // Destructor
String& operator=(const String& right); // Assignment operator
String& operator+=(const String& right);
int length() const;
char& operator[](int index);
char operator[](int index) const;
private:
char* buffer;
int len;
};
String::String(const char p[]) { // Determine number of characters in string (strlen(p)) len = 0; while (p[len] != '\0') len++; // Allocate buffer array, remember to make space for NULL character buffer = new char[len + 1]; // Copy new characters (strcpy( buffer, p )) for (int i = 0; i < len; i++) buffer[i] = p[i]; buffer[len] ='\0'; }(Operators as described in chptr. 17)
String::String()
{
len = 0;
buffer = NULL; // No need to allocate array to hold zero characters
}
String::String(const String& right)
{
int n = right.length();
buffer = new char[n + 1];
for (int i = 0; i < n; i++)
buffer[i] = right[i];
buffer[n] = '\0';
}
String first("Fred");
String second(first); // second is initialized from first using copy constructor
String third = first; // Also uses copy constructor
class Employee
{
public:
Employee(String employee_name, double initial_salary);
. . .
private:
String name;
double salary;
};
Employee::Employee(String employee_name, double initial_salary)
: name(employee_name), salary(initial_salary)
{
}
class TeachingAssistant : public Employee
public:
TeachingAssistant(String student_name);
};
TeachingAssistant::TeachingAssistant(String student_name)
// Teaching assistants all get same starting salary
: Employee(student_name, 5000)
{
}
class PartDescription
{
public:
PartDescription(String part_name,
int inventory_number);
private:
const String name;
const int part_number:
vector<PartDescription*> subcomponents;
};
PartDescription::PartDescription(String part_name,
int inventory_number)
: name(part_name), part_number(inventory_number),
subcomponents(3) {}
String& String::operator=(const String& right)
{
if (this != &right)
{
delete[] buffer; // Get rid of old buffer
len = right.length();
buffer = new char[len + 1];
for (int i = 0; i < len; i++)
buffer[i] = right[i];
buffer[len] = '\0';
}
return *this;
}
Syntax 17.2 :
Overloading Operator Definition
ClassName::~ClassName()
{
statements
}
|
class Employee
{
virtual ~Employee();
};
Employee::~Employee()
{ cout << "Goodbye Employee\n"; }
class TeachingAssistant : public Employee
{
~TeachingAssistant();
};
TeachingAssistant::~TeachingAssistant()
{ cout << "Goodbye TeachingAssistant\n"; }
Now consider the following:
Employee *a = new TeachingAssistant();
delete a;
Consider our String class: change the semantics for the assignment of strings so that two strings would share a common internal data buffer: