Classes with Other Classes as Member Data in C++

By: Kamini Viewed: 153263 times  Printer Friendly Format    

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.

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
17:  class  Rectangle
18:  {
19:     public:
20:        Rectangle (int top, int left, int bottom, int right);
21:        ~Rectangle () {}
23:        int GetTop() const { return itsTop; }
24:        int GetLeft() const { return itsLeft; }
25:        int GetBottom() const { return itsBottom; }
26:        int GetRight() const { return itsRight; }
28:        Point  GetUpperLeft() const { return itsUpperLeft; }
29:        Point  GetLowerLeft() const { return itsLowerLeft; }
30:        Point  GetUpperRight() const { return itsUpperRight; }
31:        Point  GetLowerRight() const { return itsLowerRight; }
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;}
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; }
43:        int GetArea() const;
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


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;
10:        itsUpperLeft.SetX(left);
11:        itsUpperLeft.SetY(top);
13:        itsUpperRight.SetX(right);
14:        itsUpperRight.SetY(top);
16:        itsLowerLeft.SetX(left);
17:        itsLowerLeft.SetY(bottom);
19:        itsLowerRight.SetX(right);
20:        itsLowerRight.SetY(bottom);
21:  }
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:  }
33:  int main()
34:  {
35:        //initialize a local Rectangle variable
36:        Rectangle MyRectangle (100, 20, 50, 80 );
38:        int Area = MyRectangle.GetArea();
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 first program 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  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 the above program. 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.

Most Viewed Articles (in C++ )

Latest Articles (in C++)

Comment on this tutorial