This is a continuation from the previous Module. The source code for this tutorial is available inC++ Data Encapsulation source codes.
The C++ programming abilities that must be covered in this session: Able to understand and use:
13.7 new and delete operators
TypeName *typeNamePtr;
typeNamePtr = malloc(sizeof(TypeName));
typeNamePtr = new TypeName;
delete typeNamePtr;
double *Ptr = new double (4.2345);
ObjectPtr = new int[10][10];
delete[ ] ObjectPtr;
13.8 An Object With A Pointer To Another Object
|
1. // program oblist.cpp
2. // object and list
3.
4. #include <iostream>
5. using namespace std;
6.
7. // a class declaration part
8. class wall
9. {
10. int length;
11. int width;
12. wall *another_wall; // a pointer variable
13. public:
14. wall(void);
15. // a constructor declaration
16. void set(int new_length, int new_width);
17. int get_area(void);
18. void point_at_next(wall *where_to_point);
19. wall *get_next(void);
20. };
21.
22. // a class implementation part
23. wall::wall(void)
24. // a constructor implementation
25. {
26. length = 8;
27. width = 8;
28. another_wall = NULL;
29. }
30.
31. // this method will set a wall size to the input parameters
32. void wall::set(int new_length, int new_width)
33. {
34. length = new_length;
35. width = new_width;
36. }
37.
38. // this method will calculate and return the area of a wall instance
39. int wall::get_area(void)
40. {
41. return (length * width);
42. }
43.
44. // this method causes the pointer to point to the input parameter
45. void wall::point_at_next(wall *where_to_point)
46. {
47. another_wall = where_to_point;
48. }
49.
50. // this method returns the wall the current one points to
51. wall *wall::get_next(void)
52. {
53. return another_wall;
54. }
55.
56. // main program
57. void main()
58. {
59. wall small, medium, large;
60. // objects are instantiated, of type class wall
61. wall *wall_pointer;
62. // wall *point;
63. // a pointer to a wall
64.
65. small.set(5, 7);
66. large.set(15, 20);
67.
68. // point = new wall;
69. // use the defaults value supplied by the constructor
70. cout<<"Using small.set(5, 7):\n";
71. cout<<"----------------------\n";
72. cout<<"Area of the small wall surface is "<<small.get_area()<<"\n\n";
73. cout<<"Using default/constructor value\n";
74. cout<<"-------------------------------\n";
75. cout<<"Area of the medium wall surface is "<<medium.get_area()<<"\n\n";
76. cout<<"Using large.set(15, 20):\n";
77. cout<<"------------------------\n";
78. cout<<"Area of the large wall surface is "<<large.get_area()<<"\n\n";
79.
80. small.point_at_next(&medium);
81. medium.point_at_next(&large);
82.
83. wall_pointer = &small;
84. wall_pointer = wall_pointer->get_next();
85.
86. cout<<"The wall’s pointer pointed to has area "<<wall_pointer
87. ->get_area()<<"\n";
88.
89. // system("pause");
90. }

The constructor contains the statement in line 28 as shown below, which assigns the pointer named another_box the value ofNULL to initialize the pointer. Don’t allow any pointer to point off into space, but initialize all pointers to point to something.
another_wall = NULL;
By assigning the pointer within the constructor, you guarantee that every object of this class will automatically have its pointer initialized.
Two additional methods are declared in lines 18 and 19 as in the following code with the one in line 19 having a construct we have not yet mentioned in this Module. This method returns a pointer to an object of the wall class. As you are aware, you can return a pointer to astruct in standard C, and this is a parallel construct in C++.
void point_at_next(wall *where_to_point);
wall *get_next(void);
As shown below, the implementation in lines 51 through 54 returns the pointer stored as a member variable within the object. We will see how this is used when we get to the actual program.
wall *wall::get_next(void)
{
return another_wall;
}
An extra pointer named wall_pointer is defined in the main program for later use and in line 80 we make the embedded pointer within thesmall wall point to themedium wall. Line 81 makes the embedded pointer within the medium wall point to the large wall as shown below:
small.point_at_next(&medium);
medium.point_at_next(&large);
We have effectively generated a linked list with three elements. In line 83 we make theextra pointer point to thesmall wall. Continuing in line 84 we use it to refer to the small wall and update it to the value contained in the small wall which is the address of the medium wall. The code segment is shown below:
wall_pointer = &small;
wall_pointer = wall_pointer->get_next();

We have therefore traversed from one element of the list to another by sending a message to one of the objects. If line 84 were repeated exactly as shown, it would cause the extra pointer to refer to the large wall, and we would have traversed the entire linked list which is only composed of three elements.
Figure 13.2 is a graphical representation of a portion of each object data space following the program execution.
Compile and run this program in preparation for our next program example.
Keep in mind that a better solution for related list constructs can be found in theStandard Template Library, using list containers.
The pointerthis is defined within any object as being a pointer to the object in which it is contained. It is a pointer and explicitly defined as:
class_name *this;
And is initialized to point to the object for which the member function is invoked. this pointer is most useful when working with pointers and especially with a linked list when you need to reference a pointer to the object you are inserting into the list.
The pointerthis is available for this purpose and can be used in any object. Actually the proper way to refer to any variable within a list is through the use of the predefined pointerthis, by writing:
this→variable_name
But the compiler assumes this pointer is used, and we can simplify every reference by omitting this pointer.
If used explicitly, each object can determine its own address by using this keyword.
this pointer can be used to prevent an object from being assigned to itself.
The following example demonstrates the use of the this pointer explicitly to enable a member function of class ThiPoint to display the private data c of theThiPoint object.
// using the this pointer explicitly
// to refer to object members
#include <iostream>
using namespace std;
class ThiPoint
{
int c;
public:
ThiPoint(int);
void display();
};
ThiPoint::ThiPoint(int a){ c = a;} // just a constructor
void ThiPoint::display()
{
cout<<"c = "<<c<<endl;
cout<<"this->c = "<<this->c<<endl;
cout<<"(*this).c = "<<(*this).c<<endl;
// use parentheses for (*this).c because
// dot has higher precedence than *
}
void main(void)
{
ThiPoint b(10);
b.display();
}
----------------------------------------------------------------------

Examine the program named oblink.cpp carefully and this program is a complete example of a linked list written in a simple object oriented notation. This program is very similar to the last one, oblist.cpp until we get to the main() program.
1. // program oblink.cpp,
2. // an object link list
3. #include <iostream>
4. using namespace std;
5.
6. // class declaration part
7. class wall
8. {
9. int length;
10. int width;
11. wall *another_wall; // a pointer variable
12. public:
13. wall(void);
14. // a constructor declaration
15. void set(int new_length, int new_width);
16. int get_area(void);
17. void point_at_next(wall *where_to_point);
18. wall *get_next(void);
19. };
20.
21. // a class implementation part
22. wall::wall(void)
23. // constructor implementation
24. {
25. length = 8;
26. width = 8;
27. another_wall = NULL;
28. }
29.
30. // this method will set a wall size to the input parameters
31. void wall::set(int new_length, int new_width)
32. {
33. length = new_length;
34. width = new_width;
35. }
36.
37. // this method will calculate and return the area of a wall instance
38. int wall::get_area(void)
39. {
40. return (length * width);
41. }
42.
43. // this method causes the pointer to point to the input parameter
44. void wall::point_at_next(wall *where_to_point)
45. {
46. another_wall = where_to_point;
47. }
48.
49. // this method returns the wall the current one points to
50. wall *wall::get_next(void)
51. {
52. return another_wall;
53. }
54.
55. // main program
56. void main()
57. {
58. wall *start = NULL; // always point to the start of the list
59. wall *temp = NULL; // working pointer, initialize with NULL
60. wall *wall_pointer; // use for object wall instances
61.
62. // generate the list
63. for(int index = 0; index < 8; index++)
64. {
65. wall_pointer = new wall; // a new object instances
66. wall_pointer->set(index+1, index+3);
67.
68. if(start == NULL)
69. start = wall_pointer; // first element in list
70. else
71. temp->point_at_next(wall_pointer); // next element, link list
72.
73. temp = wall_pointer;
74. // print the list
75. cout<<"Starting with wall_pointer
76. ->set("<<(index+1)<<","<<(index+3)<<")"<<"\n";
77. cout<<" New Wall's surface area is " <<temp->get_area() << "\n";
78. }
79.
80. // clean up
81. temp = start;
82. do {
83. temp = temp->get_next();
84. delete start;
85. start = temp;
86. } while (temp != NULL);
87.
88. // system("pause");
89. }

void point_at_next(wall *where_to_point); wall *get_next(void);
wall *start = NULL; // always point to the start of the list wall *temp = NULL; // working pointer, initialize with NULL wall *wall_pointer; // use for object wall instances |
The pointer named wall_pointer will be used to instantiate of each object. We execute the loop in lines 63 through 78 as shown below, to generate the list where line 65 dynamically allocates a new object of the wall class and line 66 fill it with some data for illustration.
for(int index = 0; index < 8; index++)
{
wall_pointer = new wall; // new object instances
wall_pointer->set(index+1, index+3);
...
...
}
If this is the first element in the list, the start pointer is set to point to this element, but if the elements already exist, the last element in the list is assigned to point to the new element. In either case, the temp pointer is assigned to point to the last element of the list, in preparation for adding another element if any.
In line 73, the pointer named temp is caused to point to the first element at the beginning and it is used to increment its way through the list by updating itself in line 71 during each pass through the loop. When temp has the value ofNULL, which it gets from the list, we are finished traversing the list.
Finally, we delete the entire list by starting at the beginning and deleting one element each time we pass through the loop in lines 81 through 86. The code segment is shown below:
temp = start;
do{
temp = temp->get_next();
delete start;
start = temp;
} while (temp != NULL);
This program generates a linked list of ten elements, each element being an object of class wall.
Compile and run this program example.
Keep in mind that a better solution for list can be found in theStandard Template Library, using list containers.
Examine the program named obnest.cpp for an example of nesting classes which results in nested objects.
This program example contains a class named box which contains an object of another class embedded within it in line 25, themail_info class as shown below. It is depicted graphically in figure 13.3.
This object is available for use only within the class implementation ofbox because that is where it is defined, it is local scope.
mail_info label;

Themain() program has objects of classbox defined but no objects of classmail_info, so the mail_info class cannot be referred to in the main() program. In this case, the mail_info class object is meant to be used internally to the box class and one example is given in line 32 as shown below where a message is sent to the label.set() method to initialize the variables.
label.set(ship, post);
Additional methods could be used as needed, but these are given as an illustration of how they can be called.
1. // program obnest.cpp
2. #include <iostream>
3. using namespace std;
4.
5. // first class declaration
6. class mail_info
7. {
8. int shipper;
9. int postage;
10. public:
11. void set(int input_class, int input_postage)
12. {
13. shipper = input_class;
14. postage = input_postage;
15. }
16. int get_postage(void)
17. { return postage;}
18. };
19.
20. // a second class declaration
21. class box
22. {
23. int length;
24. int width;
25. mail_info label;
26.
27. public:
28. void set(int l, int w, int ship, int post)
29. {
30. length = l;
31. width = w;
32. label.set(ship, post);
33. // accessing the first class, mail_info set() method
34. }
35.
36. int get_area(void) { return (length * width);}
37. };
38.
39. // main program
40. void main()
41. {
42. box small, medium, large; // object instances
43.
44. small.set(2,4,1,35);
45. medium.set(5,6,2,72);
46. large.set(8,10,4,98);
47.
48. cout<<"Normal class-->small.get_area()\n";
49. cout<<"-------------------------------\n";
50. cout<<"Area of small box surface is "<<small.get_area()<< "\n\n";
51. cout<<"Normal class-->medium.get_area()\n";
52. cout<<"-------------------------------\n";
53. cout<<"Area of medium box surface is "<<medium.get_area() << "\n\n";
54. cout<<"Normal class-->large.get_area()\n";
55. cout<<"-------------------------------\n";
56. cout<<"Area of large box surface is "<<large.get_area()<<"\n\n";
57.
58. // system("pause");
59. }

The fact is that there are never any objects of the mail_info class declared directly in the main() program, they are inherently declared when the enclosing objects of classbox are declared.
The objects of the mail_info class could be declared and used in the main() program if needed, but they are not in this program example. In order to be complete, thebox class should have one or more methods to use the information stored in the object of the mail_info class.
Compile and run this program.
tenouk C++ object oriented tutorial: encapsulation code samples