|
|
|
|
Composition vs. inheritance (revisited)
One of the clearest ways to determine
whether you should be using composition or inheritance is by asking whether
you’ll ever need to upcast from your new class. Earlier in this chapter,
the Stack class was specialized using inheritance. However, chances are
the StringStack objects will be used only as string containers and
never upcast, so a more appropriate alternative is composition:
//: C14:InheritStack2.cpp
// Composition vs. inheritance
#include "../C09/Stack4.h"
#include "../require.h"
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
class StringStack {
Stack stack; // Embed instead of inherit
public:
void push(string* str) {
stack.push(str);
}
string* peek() const {
return (string*)stack.peek();
}
string* pop() {
return (string*)stack.pop();
}
};
int main() {
ifstream in("InheritStack2.cpp");
assure(in, "InheritStack2.cpp");
string line;
StringStack textlines;
while(getline(in, line))
textlines.push(new string(line));
string* s;
while((s = textlines.pop()) != 0) // No cast!
cout << *s << endl;
} ///:~
The file is identical to
InheritStack.cpp, except that a Stack object is embedded in
StringStack, and member functions are called for the embedded object.
There’s still no time or space overhead because the subobject takes up the
same amount of space, and all the additional type checking happens at compile
time.
Although it tends to be more confusing,
you could also use private inheritance to express “implemented in
terms of.” This would also solve the problem adequately. One place it
becomes important, however, is when multiple
inheritance might be warranted.
In that case, if you see a design in which composition can be used instead of
inheritance, you may be able to eliminate the need for multiple
inheritance.
|
|
|