|

Dog
objects are Mammal objects. This is the essence
of the is-a relationship. When Fido is created,
his base constructor is called first, creating a
Mammal. Then the Dog constructor is called, completing
the construction of the Dog object. Because we gave
Fido no parameters, the default constructor was
called in each case. Fido doesn’t exist until he
is completely constructed, which means that both
his Mammal part and his Dog part must be constructed.
Thus, both constructors must be called.
When
Fido is destroyed, first the Dog destructor will
be called and then the destructor for the Mammal
part of Fido. Each destructor is given an opportunity
to clean up after its own part of Fido. Remember
to clean up after your Dog! Listing 12.3 demonstrates
this.
Listing
12.3. Constructors and destructors called.
1:
//Listing 12.3 Constructors and destructors called.
2:
3:
#include <iostream.h>
l
the attributes of a Dog. Thus, Fido knows how to
WagTail(), but also knows how to Speak() and Sleep().
Dog
objects are Mammal objects. This is the essence
of the is-a relationship. When Fido is created,
his base constructor is called first, creating a
Mammal. Then the Dog constructor is called, completing
the construction of the Dog object. Because we gave
Fido no parameters, the default constructor was
called in each case. Fido doesn’t exist until he
is completely constructed, which means that both
his Mammal part and his Dog part must be constructed.
Thus, both constructors must be called.
When
Fido is destroyed, first the Dog destructor will
be called and then the destructor for the Mammal
part of Fido. Each destructor is given an opportunity
to clean up after its own part of Fido. Remember
to clean up after your Dog! Listing 12.3 demonstrates
this.
Listing
12.3. Constructors and destructors called.
1:
//Listing 12.3 Constructors and destructors called.
2:
3:
#include <iostream.h>
4:
enum BREED { YORKIE, CAIRN, DANDIE, SHETLAND, DOBERMAN,
LAB };
5:
6:
class Mammal
7:
{
8:
public:
9:
// constructors
10:
Mammal();
11:
~Mammal();
12:
13:
//accessors
14:
int GetAge() const { return itsAge; }
15:
void SetAge(int age) { itsAge = age; }
16:
int GetWeight() const { return itsWeight; }
17:
void SetWeight(int weight) { itsWeight = weight;
}
18:
19:
//Other methods
20:
void Speak() const { cout << "Mammal sound!\n";
}
21:
void Sleep() const { cout << "shhh. I’m sleeping.\n";
}
22:
23:
24:
protected:
25:
int itsAge;
26:
int itsWeight;
27:
};
28:
29:
class Dog : public Mammal
30:
{
31:
public:
32:
33:
// Constructors
34:
Dog();
35:
~Dog();
36:
37:
// Accessors
38:
BREED GetBreed() const { return itsBreed; }
39:
void SetBreed(BREED breed) { itsBreed = breed; }
40:
41:
// Other methods
42:
void WagTail() { cout << "Tail wagging...\n";
}
43:
void BegForFood() { cout << "Begging for food...\n";
}
44:
45:
private:
46:
BREED itsBreed;
47:
};
48:
49:
Mammal::Mammal():
50:
itsAge(1),
51:
itsWeight(5)
52:
{
53:
cout << "Mammal constructor...\n";
54:
}
55:
56:
Mammal::~Mammal()
57:
{
58:
cout << "Mammal destructor...\n";
59:
}
60:
61:
Dog::Dog():
62:
itsBreed(YORKIE)
63:
{
64:
cout << "Dog constructor...\n";
65:
}
66:
67:
Dog::~Dog()
68:
{
69:
cout << "Dog destructor...\n";
70:
}
71:
int main()
72:
{
73:
Dog fido;
74:
fido.Speak();
75:
fido.WagTail();
76:
cout << "Fido is " << fido.GetAge()
<< " years old\n";
77:
return 0;
78:
}
OUTPUT:
Mammal constructor...
Dog constructor...
Mammal sound!
Tail wagging...
Fido is 1 years old
Dog destructor...
Mammal destructor...
ANALYSIS: Listing 12.3 is just like
Listing 12.2, except that the constructors and destructors
now print to the screen when called. Mammal’s constructor
is called, then Dog’s. At that point the Dog fully
exists, and its methods can be called. When fido
goes out of scope, Dog’s destructor is called, followed
by a call to Mammal’s destructor.
Passing
Arguments to Base Constructors
It
is possible that you’ll want to overload the constructor
of Mammal to take a specific age, and that you’ll
want to overload the Dog constructor to take a breed.
How do you get the age and weight parameters passed
up to the right constructor in Mammal? What if Dogs
want to initialize weight but Mammals don’t?
Base
class initialization can be performed during class
initialization by writing the base class
Mammals
don’t?
Base
class initialization can be performed during class
initialization by writing the base class name, followed
by the parameters expected by the base class. Listing
12.4 demonstrates this.
Listing
12.4. Overloading constructors in derived classes.
1:
//Listing 12.4 Overloading constructors in derived
classes
2:
3:
#include <iostream.h>
4:
enum BREED { YORKIE, CAIRN, DANDIE, SHETLAND, DOBERMAN,
LAB };
5:
6:
class Mammal
7:
{
8:
public:
9:
// constructors
10:
Mammal();
11:
Mammal(int age);
12:
~Mammal();
13:
14:
//accessors
15:
int GetAge() const { return itsAge; }
16:
void SetAge(int age) { itsAge = age; }
17:
int GetWeight() const { return itsWeight; }
18:
void SetWeight(int weight) { itsWeight = weight;
}
19:
20:
//Other methods
21:
void Speak() const { cout << "Mammal sound!\n";
}
22:
void Sleep() const { cout << "shhh. I’m sleeping.\n";
}
23:
24:
25:
protected:
26:
int itsAge;
27:
int itsWeight;
28:
};
29:
30:
class Dog : public Mammal
31:
{
32:
public:
33:
34:
// Constructors
35:
Dog();
36:
Dog(int age);
37:
Dog(int age, int weight);
38:
Dog(int age, BREED breed);
39:
Dog(int age, int weight, BREED breed);
40:
~Dog();
41:
42:
// Accessors
43:
BREED GetBreed() const { return itsBreed; }
44:
void SetBreed(BREED breed) { itsBreed = breed; }
45:
46:
// Other methods
47:
void WagTail() { cout << "Tail wagging...\n";
}
48:
void BegForFood() { cout << "Begging for food...\n";
}
49:
50:
private:
51:
BREED itsBreed;
52:
};
53:
54:
Mammal::Mammal():
55:
itsAge(1),
56:
itsWeight(5)
57:
{
58:
cout << "Mammal constructor...\n";
59:
}
60:
61:
Mammal::Mammal(int age):
62:
itsAge(age),
63:
itsWeight(5)
64:
{
65:
cout << "Mammal(int) constructor...\n";
66:
}
67:
68:
Mammal::~Mammal()
69:
{
70:
cout << "Mammal destructor...\n";
71:
}
72:
73:
Dog::Dog():
74:
Mammal(),
75:
itsBreed(YORKIE)
76:
{
77:
cout << "Dog constructor...\n";
78:
}
79:
80:
Dog::Dog(int age):
81:
Mammal(age),
82:
itsBreed(YORKIE)
83:
{
84:
cout << "Dog(int) constructor...\n";
85:
}
86:
87:
Dog::Dog(int age, int weight):
88:
Mammal(age),
89:
itsBreed(YORKIE)
90:
{
91:
itsWeight = weight;
92:
cout << "Dog(int, int) constructor...\n";
93:
}
94:
95:
Dog::Dog(int age, int weight, BREED breed):
96:
Mammal(age),
97:
itsBreed(breed)
98:
{
99:
itsWeight = weight;
100:
cout << "Dog(int, int, BREED) constructor...\n";
101:
}
102:
103:
Dog::Dog(int age, BREED breed):
104:
Mammal(age),
105:
itsBreed(breed)
106:
{
107:
cout << "Dog(int, BREED) constructor...\n";
108:
}
109:
110:
Dog::~Dog()
111:
{
112:
cout << "Dog destructor...\n";
113:
}
114:
int main()
115:
{
116:
Dog fido;
117:
Dog rover(5);
118:
Dog buster(6,8);
119:
Dog yorkie (3,YORKIE);
120:
Dog dobbie (4,20,DOBERMAN);
121:
fido.Speak();
122:
rover.WagTail();
123:
cout << "Yorkie is " << yorkie.GetAge()
<< " years old\n";
124:
cout << "Dobbie weighs ";
125:
cout << dobbie.GetWeight() << " pounds\n";
126:
return 0;
127:
}
NOTE: The output has been numbered
here so that each line can be referred to in the
analysis.
OUTPUT:
1: Mammal constructor...
2: Dog constructor...
3: Mammal(int) constructor...
4: Dog(int) constructor...
5: Mammal(int) constructor...
6: Dog(int, int) constructor...
7: Mammal(int) constructor...
8: Dog(int, BREED) constructor....
9: Mammal(int) constructor...
10: Dog(int, int, BREED) constructor...
11: Mammal sound!
11: Mammal sound!
12: Tail wagging...
13: Yorkie is 3 years old.
14: Dobbie weighs 20 pounds.
15: Dog destructor. . .
16: Mammal destructor...
17: Dog destructor...
18: Mammal destructor...
19: Dog destructor...
20: Mammal destructor...
21: Dog destructor...
22: Mammal destructor...
23: Dog destructor...
24: Mammal destructor...
ANALYSIS: In Listing 12.4, Mammal’s
constructor has been overloaded on line 11 to take
an integer, the Mammal’s age. The implementation
on lines 61-66 initializes itsAge with the value
passed into the constructor and initializes itsWeight
with the value 5.
Dog
has overloaded five constructors, on lines 35-39.
The first is the default constructor. The second
takes the age, which is the same parameter that
the Mammal constructor takes. The third constructor
takes both the age and the weight, the fourth takes
the age and breed, and the fifth takes the age,
weight, and breed.
Note
that on line 74 Dog’s default constructor calls
Mammal’s default constructor. Although it is not
strictly necessary to do this, it serves as documentation
that you intended to call the base constructor,
which takes no parameters. The base constructor
would be called in any case, but actually doing
so makes your intentions explicit.
The
implementation for the Dog constructor, which takes
an integer, is on lines 80-85. In its initialization
phase (lines 81-82), Dog initializes its base class,
passing in the parameter, and then it initializes
its breed.
Another
Dog constructor is on lines 87-93. This one takes
two parameters. Once again it initializes its base
class by calling the appropriate constructor, but
this time it also assigns weight to its base class’s
variable itsWeight. Note that you cannot assign
to the base class variable in the initialization
phase. Because Mammal does not have a constructor
that takes this parameter, you must do this within
the body of the Dog’s constructor.
Walk
through the remaining constructors to make sure
you are comfortable with how they work. Note what
is initialized and what must wait for the body of
the constructor.
The
output has been numbered so that each line can be
referred to in this analysis. The first two lines
of output represent the instantiation of Fido, using
the default constructor.
In
the output, lines 3 and 4 represent the creation
of rover. Lines 5 and 6 represent buster. Note
In
the output, lines 3 and 4 represent the creation
of rover. Lines 5 and 6 represent buster. Note that
the Mammal constructor that was called is the constructor
that takes one integer, but the Dog constructor
is the constructor that takes two integers.
After
all the objects are created, they are used and then
go out of scope. As each object is destroyed, first
the Dog destructor and then the Mammal destructor
is called, five of each in total.
|