Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Channels ▼
RSS

Conversations: Back to Base-ics


September 2001 C++ Experts Forum/Conversations


"...their fleet will reach our orbiting facilities in three days," the commander was saying. His breath drifted hazily in the air; we were standing in the ice cavern, the only room large enough to hold us all. "We do not know their intentions; we continue to have problems with our own communications equipment. It could be that they misunderstand our situation. We are doing everything we can to contact them."

I had already been having my doubts as to how real our own communications problems really were, and how much they were an invention to keep the Asians in particular away from our amazing discoveries here on the Europan surface. We were continuing to excavate and explore the alien city we had found frozen, preserved beneath the ice, but the work was going more slowly now as we struggled to make sense of the few dozen different artifacts we'd discovered. None of us who had been selected for work here were Asians, and I'm sure I wasn't the only one to notice that convenient little fact.

"We're confident in a successful outcome," the commander was finishing. "New watch schedules have been posted that will take effect at 0900 tomorrow for the duration until this situation has been resolved. In the meantime, concentrate on your work, especially those of you assigned to investigate the artifacts, and don't worry. Dismissed."

At the mess hall, I was still mulling it over when an aide approached us. "Jeannine, Nancy wants to see you after the next watch." Jeannine nodded.

I looked up and chuckled as the aide left. "What?" Jeannine asked.

"Oh," I waved, "just the same old same old."

Jeannine sighed in exasperation. "Why does every conversation we have remind you of your first job?"

"That," I smiled, "actually has a lot to do with you..."


As usual, I was struggling with what should have been a simple design problem. It didn't help that I was still a little foggy from the Labor Day weekend. Wendy had just started her maternity leave, so I couldn't bounce any ideas off her.

I had to introduce a new class into the project. I had found an existing class, which was fairly close to what I wanted. Problem was, I couldn't decide on the exact relationship between the existing class and the new one. I knew I didn't want to derive publicly from the existing class, because there was no IS-A relationship between the two. Layering was not an option, as I had to override some virtual functions. I knew I needed either private inheritance, to model Is-Implemented-In-Terms-Of, or I needed to extract the common functionality into a new base class.

As I was mulling my options, I thought that this would be an appropriate moment for the Guru to show up. I whirled around in my chair — but nobody was there. Feeling rather foolish, I turned back to my keyboard. "Well," said I to myself, "I'm going to have to decide one way or another."

"Wise decisions are sometimes difficult to make." I jumped at the Guru's quiet voice beside me. I glanced at her askance, and she continued: "How will you decide your options?"

"That's what I'm having trouble with," I admitted, as my heart rate came back down. "Scott Meyers's Item 40 suggests an Is Implemented In Terms Of relationship, to take advantage of code in another class that already exists but is not conceptually related [1]. His example is a Set that is implemented in terms of a List." I showed the Guru the example:

template<class T>
class Set {
private:
    List<T> rep;  // representation for a set
public:
    // ...
};

"But then Item 43," I continued, "suggests that if two classes share common code, then they should inherit from a common base class. His example there is two CartoonCharacter classes, Cricket and Grasshopper, which derive from a newly-introduced, common base called Insect." I showed the Guru the second example:

class CartoonCharacter { /* ... */ };
class Insect : public CartoonCharacter { /* ... / };
class Grasshopper : public Insect { /* ... / };
class Cricket : public Insect { /* ... */ };

The Guru half smiled. "Yes, but Item 43 really only applies if the classes are related."

"My child," I reminded, sotto voce.

"...if the classes are related, my child," she nodded, amending. There were other people within earshot, after all, and appearances had to be maintained.

"Yes, but," I echoed in my turn, "here's my quandary. I could apply the technique in Item 43 — factoring functionality into a common base class — to the example in Item 40. Instead of implementing a Set in terms of a List, why not create a new class, say Container, which serves as a base class for both Set and List? In my case, with this new class I have to write, I can envision a common base class for my new class and for the existing class."

"Ah, I see," the Guru nodded. "Your question essentially works out to this: How do you distinguish between Item 40's 'taking advantage of code written for an existing class', and Item 43's 'sharing code'? On the surface the two do seem to be quite similar." The Guru paused in thought for a moment. "I would suggest that you might follow this sequence of thought:

"In general, when you are adding a new class to a project, and that class is very similar to an existing class, you will frequently have three options: derive one class from the other, create a common base class from which both the new and existing classes will be derived, and implement one class in terms of the other class.

"The simple case, of course, is the first one — does the relationship model an IS-A relationship? If so, then publicly derive the new class from the existing class, or vice versa."

"Ah, yes," I interjected, as I began jotting in my notebook. "The one thing Meyers wants us to remember about C++, and it ain't 1066 [2]!"

The Guru rolled her eyes. "Examine the nature of the shared or common code," she continued and added, "which assumes, by the way, that you have the source code of the existing class available to you; if you do not, then obviously you cannot refactor the existing class, and the design is now decided — you must Implement In Terms Of. But for this project, you have the source code available, and you examine the potentially shared code: Is the code truly common? That is, does each of the classes call the same actual function — not just a function with the same name, but the same actual function? In Meyers's Cricket and Grasshopper example, both call the same singCustomization function. The customization functions are truly common code. On the other hand, if you were to introduce the Container base class, its insert function would not likely work for both Set and List. One or both of the classes would have to provide their own, unique overrides of the insert function. The code is not truly common, so a common base class is not suggested.

"Examine the two classes. Are the existing and new classes conceptually related to some useful base class? How useful is the Container class you propose? As an example, consider the Standard container classes — there is no class called std::container or its equivalent. Nor can there be — why not?"

"Uh," I uhhed, "because the interfaces aren't identical?"

"Close enough," she allowed. "Their interfaces vary, and the commonalities are specified by use cases, not by specific function signatures. Wanting to invent a base class whose sole purpose is to unite two otherwise unrelated classes suggests that we are wanting what is perverse; it suggests that, instead, we should perhaps be Implementing In Terms Of."

"Wait a second," I interrupted. "The Insect class was invented just to unite the two other classes."

"True, but the Cricket and Grasshopper classes were already related — they are both ultimately descended from the CartoonCharacter class. In addition, the Insect class provides additional functionality that both Cricket and Grasshopper build on. Therefore, the Insect class is a meaningful class in its own right and provides a cohesive and internally consistent abstraction.

"Next," she continued, "if the existing class has protected members you wish to access, you may want to consider using non-public inheritance.

"Finally, ask yourself: Would Implementing In Terms Of introduce multiple inheritance, where using a common base class would not? Multiple inheritance is inherently more complex than single inheritance. Prefer the simpler solution, if possible."

I was awash, though still floating gamely in the sea of information. I needed time to digest. "Great, thanks for the help, I think. I mean, I think I know how to figure it out now!"

The Guru bowed her head. "Oh, I heard from Wendy's husband, Tom, this morning."

"And the news is...?" I grinned excitedly.

"A baby girl, seven pounds 13 ounces, born at 2:18 a.m. on Monday morning. Her name is Jeannine Nancy."


"Jeannine?" She lifted her eyebrows.

I couldn't help it: "Yes, Jeannine: Jeannine," I smiled. "C'mon, we'd better get back to the lab."

References

[1] Scott Meyers. Effective C++, 2nd Edition, Items 40, 42, and 43 (Addison-Wesley, 1997).

[2] Scott Meyers. Effective C++, 2nd Edition, Item 35 (Addison-Wesley, 1997).

Jim Hyslop is a senior software designer at Leitch Technology International Inc. He can be reached at [email protected].

Herb Sutter is an independent consultant and secretary of the ISO/ANSI C++ standards committee. He is also one of the instructors of The C++ Seminar (<www.gotw.ca/cpp_seminar>). Herb can be reached at [email protected].


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.