Online Book Reader

Home Category

Professional C__ - Marc Gregoire [112]

By Root 1282 0
the parent class because they “wrap” the existing functionality in a way that provides a new interface for using it.

You can also add new functionality completely unrelated to existing functionality of the parent class. For example, you could add a method that will retrieve alternative forecasts from the Internet or a method that will suggest an activity based on the predicted weather.

Replacing Functionality in a Subclass

The other major technique for subclassing is replacing existing functionality. The showResult() method in the WeatherPrediction class is in dire need of a facelift. MyWeatherPrediction can override this method to replace the behavior with its own implementation.

The new class definition for MyWeatherPrediction is as follows:

#include "WeatherPrediction.h"

class MyWeatherPrediction : public WeatherPrediction

{

public:

virtual void setCurrentTempCelsius(int inTemp);

virtual int getTomorrowTempCelsius();

virtual void showResult();

protected:

static int convertCelsiusToFahrenheit(int inCelsius);

static int convertFahrenheitToCelsius(int inFahrenheit);

};

Code snippet from WeatherPrediction\MyWeatherPrediction.h

A possible new user-friendly implementation follows:

void MyWeatherPrediction::showResult()

{

cout << "Tomorrow's temperature will be " <<

getTomorrowTempCelsius() << " degrees Celsius (" <<

getTomorrowTempFahrenheit() << " degrees Fahrenheit)" << endl;

cout << "Chance of rain is " << (getChanceOfRain() * 100) << " percent"

<< endl;

if (getChanceOfRain() > 0.5) {

cout << "Bring an umbrella!" << endl;

}

}

Code snippet from WeatherPrediction\MyWeatherPrediction.cpp

To clients using this class, it’s as if the old version of showResult() never existed. As long as the object is a MyWeatherPrediction object, the new version will be called.

As a result of these changes, MyWeatherPrediction has emerged as a new class with new functionality tailored to a more specific purpose. Yet, it did not require much code because it leveraged its superclass’s existing functionality.

RESPECT YOUR PARENTS


When you write a subclass, you need to be aware of the interaction between parent classes and child classes. Issues such as order of creation, constructor chaining, and casting are all potential sources of bugs.

Parent Constructors

Objects don’t spring to life all at once; they must be constructed along with their parents and any objects that are contained within them. C++ defines the creation order as follows:

1. If the class has a base class, the default constructor of the base class is executed.

2. Non-static data members of the class are constructed in the order in which they were declared.

3. The body of the class’s constructor is executed.

These rules can apply recursively. If the class has a grandparent, the grandparent is initialized before the parent, and so on. The following code shows this creation order. As a reminder, we generally advise against implementing methods directly in a class definition, as we’ve done in the code that follows. In the interest of readable and concise examples, we have broken our own rule. The proper execution will output the result 123.

class Something

{

public:

Something() { cout << "2"; }

};

class Parent

{

public:

Parent() { cout << "1"; }

};

class Child : public Parent

{

public:

Child() { cout << "3"; }

protected:

Something mDataMember;

};

int main()

{

Child myChild;

return 0;

}

Code snippet from ConstructorChain\ConstructorChain.cpp

When the myChild object is created, the constructor for Parent is called first, outputting the string "1". Next, mDataMember is initialized, calling the Something constructor, which outputs the string "2". Finally, the Child constructor is called, which outputs "3".

Note that the Parent constructor was called automatically. C++ will automatically call the default constructor for the parent class if one exists. If no default constructor exists in the parent class, or if one does exist but you wish to use an alternate constructor, you can chain the constructor just as when initializing

Return Main Page Previous Page Next Page

®Online Book Reader