C++

CLASSES WITH OTHER CLASSES AS MEMBER DATA

It is not uncommon to build up a complex class by declaring simpler classes and including them in the declaration of the more complicated class. For example, you might declare a wheel class, a motor class, a transmission class, and so forth, and then combine them into a car class. This declares a has-a relationship. A car has a motor, it has wheels, and it has a transmission.

Consider a second example. A rectangle is composed of lines. A line is defined by two points. A point is defined by an x-coordinate and a y-coordinate. Listing 6.8 shows a complete declaration of a Rectangle class, as might appear in RECTANGLE.HPP. Because a rectangle is defined as four lines connecting four points and each point refers to a coordinate on a graph, we first declare a Point class, to hold the x,y coordinates of each point. Listing 6.9 shows a complete declaration of both classes.

Listing 6.8.  Declaring a complete class.

1: // Begin Rect.hpp

2: #include <iostream.h>

3: class Point // holds x,y coordinates

4: {

5: // no constructor, use default

6: public:

7: void SetX(int x) { itsX = x; }

8: void SetY(int y) { itsY = y; }

9: int GetX()const { return itsX;}

10: int GetY()const { return itsY;}

11: private:

12: int itsX;

13: int itsY;

14: }; // end of Point class declaration

15:

16:

17: class Rectangle

18: {

19: public:

20: Rectangle (int top, int left, int bottom, int right);

21: ~Rectangle () {}

22:

23: int GetTop() const { return itsTop; }

24: int GetLeft() const { return itsLeft; }

25: int GetBottom() const { return itsBottom; }

26: int GetRight() const { return itsRight; }

27:

28: Point GetUpperLeft() const { return itsUpperLeft; }

29: Point GetLowerLeft() const { return itsLowerLeft; }

30: Point GetUpperRight() const { return itsUpperRight; }

31: Point GetLowerRight() const { return itsLowerRight; }

32:

33: void SetUpperLeft(Point Location) {itsUpperLeft = Location;}

34: void SetLowerLeft(Point Location) {itsLowerLeft = Location;}

35: void SetUpperRight(Point Location) {itsUpperRight = Location;}

36: void SetLowerRight(Point Location) {itsLowerRight = Location;}

37:

38: void SetTop(int top) { itsTop = top; }

39: void SetLeft (int left) { itsLeft = left; }

40: void SetBottom (int bottom) { itsBottom = bottom; }

41: void SetRight (int right) { itsRight = right; }

42:

43: int GetArea() const;

44:

45: private:

46: Point itsUpperLeft;

47: Point itsUpperRight;

48: Point itsLowerLeft;

49: Point itsLowerRight;

50: int itsTop;

51: int itsLeft;

52: int itsBottom;

53: int itsRight;

54: };

55: // end Rect.hpp

Listing 6.9. RECT.CPP.

1: // Begin rect.cpp

2: #include "rect.hpp"

3: Rectangle::Rectangle(int top, int left, int bottom, int right)

4: {

5: itsTop = top;

6: itsLeft = left;

7: itsBottom = bottom;

8: itsRight = right;

9:

10: itsUpperLeft.SetX(left);

11: itsUpperLeft.SetY(top);

12:

13: itsUpperRight.SetX(right);

14: itsUpperRight.SetY(top);

15:

16: itsLowerLeft.SetX(left);

17: itsLowerLeft.SetY(bottom);

18:

19: itsLowerRight.SetX(right);

20: itsLowerRight.SetY(bottom);

21: }

22:

23:

24: // compute area of the rectangle by finding corners,

25: // establish width and height and then multiply

26: int Rectangle::GetArea() const

27: {

28: int Width = itsRight-itsLeft;

29: int Height = itsTop - itsBottom;

30: return (Width * Height);

31: }

32:

33: int main()

34: {

35: //initialize a local Rectangle variable

36: Rectangle MyRectangle (100, 20, 50, 80 );

37:

38: int Area = MyRectangle.GetArea();

39:

40: cout << "Area: " << Area << "\n";

41: cout << "Upper Left X Coordinate: ";

42: cout << MyRectangle.GetUpperLeft().GetX();

43: return 0;

44: }

Output:

Area: 3000

Upper Left X Coordinate: 20

Analysis: Lines 3-14 in Listing 6.8 declare the class Point, which is used to hold a specific x,y coordinate on a graph. As written, this program doesn’t use Points much. However, other drawing methods require Points. Within the declaration of the class Point, you declare two member variables (itsX and itsY) on lines 12 and 13. These variables hold the values of the coordinates. As the x-coordinate increases, you move to the right on the graph. As the y-coordinate increases, you move upward on the graph. Other graphs use different systems. Some windowing programs, for example, increase the y-coordinate as you move down in the window.

The Point class uses inline accessor functions to get and set the X and Y points declared on lines 7-10. Points use the default constructor and destructor. Therefore, you must set their coordinates explicitly.

Line 17 begins the declaration of a Rectangle class. A Rectangle consists of four points that represent the corners of the Rectangle.

The constructor for the Rectangle (line 20) takes four integers, known as top, left, bottom, and right. The four parameters to the constructor are copied into four member variables (Listing 6.9) and then the four Points are established.

In addition to the usual accessor functions, Rectangle has a function GetArea() declared in line 43. Instead of storing the area as a variable, the GetArea() function computes the area on lines 28-29 of Listing 6.9. To do this, it computes the width and the height of the rectangle, and then it multiplies these two values.

Getting the x-coordinate of the upper-left corner of the rectangle requires that you access the UpperLeft point, and ask that point for its X value. Because GetUpperLeft()is ()a method of Rectangle, it can directly access the private data of Rectangle, including itsUpperLeft. Because itsUpperLeft is a Point and Point’s itsX value is private, GetUpperLeft() cannot directly access this data. Rather, it must use the public accessor function GetX() to obtain that value.

Line 33 of Listing 6.9 is the beginning of the body of the actual program. Until line 36, no memory has been allocated, and nothing has really happened. The only thing you’ve done is tell the compiler how to make a point and how to make a rectangle, in case one is ever needed.

In line 36, you define a Rectangle by passing in values for Top, Left, Bottom, and Right.

In line 38, you make a local variable, Area, of type int. This variable holds the area of the Rectangle that you’ve created. You initialize Area with the value returned by Rectangle’s GetArea() function.

A client of Rectangle could create a Rectangle object and get its area without ever looking at the implementation of GetArea().

RECT.HPP is shown in Listing 6.8. Just by looking at the header file, which contains the declaration of the Rectangle class, the programmer knows that GetArea() returns an int. How GetArea() does its magic is not of concern to the user of class Rectangle. In fact, the author of Rectangle could change GetArea() without affecting the programs that use the Rectangle class.

Back to Index