1. Trang chủ
  2. » Công Nghệ Thông Tin

Absolute C++ (4th Edition) part 61 pps

10 185 0
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 10
Dung lượng 129,47 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

The definition of the overloaded assignment operator would then go on to set the new member variables that were introduced in the definition of the class Derived.. If Derived is a class

Trang 1

When overloading the assignment operator in a derived class, you normally use the overloaded assignment operator from the base class To help understand the code out-line we will give, remember that an overloaded assignment operator must be defined as

a member function of the class

If Derived is a class derived from Base, then the definition of the overloaded assignment operator for the class Derived would typically begin with something like the following:

Derived& Derived::operator =(const Derived& rightSide)

{

Base::operator =(rightSide);

The first line of code in the body of the definition is a call to the assignment operator of the Base class This takes care of the inherited member variables and their data The definition of the overloaded assignment operator would then go on to set the new member variables that were introduced in the definition of the class Derived A com-plete example that includes this technique is given in the programming example “Par-tially Filled Array with Backup” later in this chapter.

A similar situation holds for defining the copy constructor in a derived class If Derived is a class derived from Base, then the definition of the copy constructor for the class Derived would typically use the copy constructor for the class Base to set the inherited member variables and their data The code would typically begin with some-thing like the following:

Derived::Derived(const Derived& Object)

: Base(Object), <probably more initializations>

{

The invocation of the base class copy constructor Base(Object) sets the inherited member variables of the Derived class object being created Note that since Object is of type Derived, it is also of type Base; therefore, Object is a legal argument to the copy constructor for the class Base A complete example that includes a copy constructor in

a base class is given in the programming example “Partially Filled Array with Backup” later in this chapter.

Of course, these techniques do not work unless you have a correctly functioning assignment operator and a correctly functioning copy constructor for the base class This means that the base class definition must include a copy constructor and that either the default automatically created assignment operator works correctly for the base class or the base class has an overloaded definition of the assignment operator

If a base class has a correctly functioning destructor, it is relatively easy to define a cor-rectly functioning destructor in a class derived from the base class When the destructor for the derived class is invoked, it automatically invokes the destructor of the base class,

Trang 2

so there is no need for the explicit writing of a call to the base class destructor; it always happens automatically The derived class destructor thus need only worry about using delete on the member variables (and any data they point to) that are added in the derived class It is the job of the base class destructor to invoke delete on the inherited member variables

If class B is derived from class A and class C is derived from class B, then when an object of class C goes out of scope, first the destructor for the class C is called, then the destructor for class B is called, and finally the destructor for class A is called Note that the order of destructor calls is the reverse of the order in which constructors are called.

We give an example of writing a destructor in a derived class in the programming example “Partially Filled Array with Backup.”

PARTIALLY FILLED ARRAY WITH BACKUP

This example presents a derived class of the partially filled array class PFArrayD that we pre-sented in Chapter 10 (Display 10.10) For reference we repeat the header file for the base class

PFArrayD in Display 14.8 We repeat as much as we will discuss of the implementation for the base class PFArrayD in Display 14.9 Note that we have made one important change to the defini-tion presented in Chapter 10 We have changed the member variables from private to protected This will allow member functions in the derived class to access the member variables by name

We will define a derived class called PFArrayDBak using PFArrayD as a base class An object of the derived class PFArrayDBak will have all the member functions of the base class PFArrayD

and can be used just like an object of the class PFArrayD, but an object of the class PFArrayD-Bak will have the following added feature: There is a member function called backup that can make a backup copy of all the data in the partially filled array, and at any later time the pro-grammer can use the member function restore to restore the partially filled array to the state it was in just before the last invocation of backup If the meaning of these added member functions

is not clear, you should peek ahead to the sample demonstration program shown in Display 14.12 The interface for the derived class PFArrayDBak is shown in Display 14.10 The class PFArrayD-Bak adds two member variables to hold a backed-up copy of the partially filled array: a member variable b of type double* that will point to a dynamic array with the backup version of the (inherited) working array, and an int member variable named usedB to indicate how much of the backed-up array b is filled with data Since there is no way to change the capacity of a

PFArrayD (or a PFArrayDBak), there is no need to back up the capacity value All the basic functions for handling a partially filled array are inherited unchanged from the base class

PFArrayD These inherited functions manipulate the inherited array a and the inherited int

variable used just as they did in the base class PFArrayD The implementation of the new member functions for the class PFArrayDBak is shown in Display 14.11 The constructors of the derived class PFArrayDBak rely on the constructors of the base class

to set up the regular partially filled array (inherited member variables a, used, and capacity)

Trang 3

Display 14.8 Interface for the Base Class PFArrayD

1 //This is the header file pfarrayd.h This is the interface for the class

2 //PFArrayD Objects of this type are partially filled arrays of doubles

3 #ifndef PFARRAYD_H

4 #define PFARRAYD_H

5 class PFArrayD

6 {

7 public:

8 PFArrayD( );

9 //Initializes with a capacity of 50

10 PFArrayD(int capacityValue);

11 PFArrayD(const PFArrayD& pfaObject);

12 void addElement(double element);

13 //Precondition: The array is not full

14 //Postcondition: The element has been added

15 bool full( ) const;

16 //Returns true if the array is full, false otherwise

17 int getCapacity( ) const;

18 int getNumberUsed( ) const;

19 void emptyArray( );

20 //Resets the number used to zero, effectively emptying the array

21 double& operator[](int index);

22 //Read and change access to elements 0 through numberUsed - 1

23 PFArrayD& operator =(const PFArrayD& rightSide);

24 ~PFArrayD( );

25 protected:

26 double *a; //for an array of doubles

27 int capacity; //for the size of the array

28 int used; //for the number of array positions currently in use

29 };

30 #endif //PFARRAYD_H

This class is the same as the one in Display 10.10, except that we have made the member variables protected instead of private

It would be good to place this class in a namespace, but we have not done so in order to keep the example simple

Trang 4

Display 14.9 Implementation for the Base Class PFArrayD (part 1 of 2)

1 #include <iostream>

2 using std::cout;

3 #include "pfarrayd.h"

4 PFArrayD::PFArrayD( ) : capacity(50), used(0)

5 {

6 a = new double[capacity];

7 }

8 PFArrayD::PFArrayD(int size) : capacity(size), used(0)

9 {

10 a = new double[capacity];

11 }

12 PFArrayD::PFArrayD(const PFArrayD& pfaObject)

13 :capacity(pfaObject.getCapacity( )), used(pfaObject.getNumberUsed( ))

14 {

15 a = new double[capacity];

16 for (int i =0; i < used; i++)

17 a[i] = pfaObject.a[i];

18 }

19 double& PFArrayD::operator[](int index)

20 {

21 if (index >= used)

23 cout << "Illegal index in PFArrayD.\n";

24 exit(0);

26 return a[index];

27 }

28

29 PFArrayD& PFArrayD::operator =(const PFArrayD& rightSide)

30 {

31 if (capacity != rightSide.capacity)

33 delete [] a;

34 a = new double[rightSide.capacity];

36 capacity = rightSide.capacity;

37 used = rightSide.used;

This is part of the implementation file pfarrayd.cpp The complete implementation is given in Display 10.11, but what is shown here is all you should need for this chapter

Trang 5

Display 14.9 Implementation for the Base Class PFArrayD (part 2 of 2)

40 return *this;

41 }

42 PFArrayD::~PFArrayD( )

43 {

44 delete [] a;

45 }

Display 14.10 Interface for the Derived Class PFArrayDBak

1 //This is the header file pfarraydbak.h This is the interface for the class

2 //PFArrayDBak Objects of this type are partially filled arrays of doubles

3 //This version allows the programmer to make a backup copy and restore

4 //to the last saved copy of the partially filled array

5 #ifndef PFARRAYDBAK_H

6 #define PFARRAYDBAK_H

7 #include "pfarrayd.h"

8 class PFArrayDBak : public PFArrayD

9 {

10 public:

11 PFArrayDBak( );

12 //Initializes with a capacity of 50

13 PFArrayDBak(int capacityValue);

14 PFArrayDBak(const PFArrayDBak& Object);

15 void backup( );

16 //Makes a backup copy of the partially filled array

17 void restore( );

18 //Restores the partially filled array to the last saved version

19 //If backup has never been invoked, this empties the partially filled

20 //array

21 PFArrayDBak& operator =(const PFArrayDBak& rightSide);

22 ~PFArrayDBak( );

23 private:

24 double *b; //for a backup of main array

25 int usedB; //backup for inherited member variable used

26 };

27 #endif //PFARRAYD_H

Trang 6

Display 14.11 Implementation for the Derived Class PFArrayDBak (part 1 of 2)

1 //This is the file pfarraydbak.cpp

2 //This is the implementation of the class PFArrayDBak

3 //The interface for the class PFArrayDBak is in the file pfarraydbak.h

4 #include "pfarraydbak.h"

5 #include <iostream>

6 using std::cout;

7 PFArrayDBak::PFArrayDBak( ) : PFArrayD( ), usedB(0)

8 {

9 b = new double[capacity];

10 }

11 PFArrayDBak::PFArrayDBak(int capacityValue) : PFArrayD(capacityValue), usedB(0)

12 {

13 b = new double[capacity];

14 }

15 PFArrayDBak::PFArrayDBak(const PFArrayDBak& oldObject)

16 : PFArrayD(oldObject), usedB(0)

17 {

18 b = new double[capacity];

19 usedB = oldObject.usedB;

20 for (int i = 0; i < usedB; i++)

21 b[i] = oldObject.b[i];

22 }

23 void PFArrayDBak::backup( )

24 {

25 usedB = used;

26 for (int i = 0; i < usedB; i++)

27 b[i] = a[i];

28 }

29

30 void PFArrayDBak::restore( )

31 {

32 used = usedB;

33 for (int i = 0; i < used; i++)

34 a[i] = b[i];

35 }

36 PFArrayDBak& PFArrayDBak::operator =(const PFArrayDBak& rightSide)

37 {

38 PFArrayD::operator =(rightSide);

39 if (capacity != rightSide.capacity)

Note that b is a copy of the array a

We do not want to use b = a;

You use a call to the base class assignment operator in order to assign to the base class member variables

Trang 7

The member function backup copies data from the partially filled array (a and used) to the backup locations b and usedB with the following code:

usedB = used;

for (int i = 0; i < usedB; i++)

b[i] = a[i];

You should note that the member variables a and used in the base class are protected and not private Otherwise, the above code would be illegal because it accesses the inherited member variables a and used by name

The member function restore simply reverses things and copies from b and usedB to a and

used

The definition of the overloaded assignment operator for the derived class PFArrayDBak begins with an invocation of the assignment operator for the base class PFArrayD This copies all the data from the member variables a, used, and capacity from the object on the right-hand side

of the assigment operator (from the parameter rightSide) to the object on the left-hand side of the assignment operator (the calling object) We are relying on the fact that this was done prop-erly in the definition of the overloaded assignment operator in the base class That is, we rely on the base class assignment operator to behave correctly when the same object (for the inherited part) occurs on both sides of the assignment operator, and we assume that the copying actions make an independent copy of the array a The code in the body of the overloaded assignment operator for the derived class PFArrayDBak needs to create a similarly independent copy of the array b

Since the objects on the right and left sides of the assignment operators may have different capacities, we must create a new array b (in most cases) This is done as follows:

if (capacity != rightSide.capacity)

{

Display 14.11 Implementation for PFArrayDBak Class (part 2 of 2)

42 b = new double[rightSide.capacity];

44 usedB = rightSide.usedB;

45 for (int i = 0; i < usedB; i++)

46 b[i] = rightSide.b[i];

47 return *this;

48 }

49 PFArrayDBak::~PFArrayDBak( )

50 {

51 delete [] b;

52 }

The destructor for the base class PFArrayD is called automatically, and it performs delete [] a;

Trang 8

delete [] b;

b = new double[rightSide.capacity];

}

Note that the Boolean expression in the if statement ensures thatb will not be deleted when the objects on either side of the assignment operator have the same capacity In particular, this ensures that when the same object appears on both sides of the assignment operator, the array b

is not deleted After this, the copying of data is routine

Note that the destructor for the class PFArrayDBak has no explicit mention of the inherited member variable a It simply sends the b array memory back to the freestore for recycling with the following:

delete [] b;

The memory for the inherited array a is also sent back to the freestore, even though you do not see any mention of a in the destructor for the derived class PFArrayDBak When the destructor for the derived class PFArrayDBak is invoked, it ends its action by automatically invoking the destructor for the base class PFArrayD, and that destructor includes the following code to dis-pose of a:

delete [] a;

A demonstration program for our class PFArrayDBak is given in Display 14.12

Display 14.12 Demonstration Program for the Class PFArrayDBak (part 1 of 3)

1 //Program to demonstrate the class PFArrayDBak

2 #include <iostream>

3 #include "pfarraydbak.h"

4 using std::cin;

5 using std::cout;

6 using std::endl;

7 void testPFArrayDBak( );

8 //Conducts one test of the class PFArrayDBak

9 int main( )

10 {

11 cout << "This program tests the class PFArrayDBak.\n";

12 char ans;

13 do

Trang 9

Display 14.12 Demonstration Program for the Class PFArrayDBak (part 2 of 3)

17 cin >> ans;

18 }while ((ans == 'y') || (ans == 'Y'));

19 return 0;

20 }

21 void testPFArrayDBak( )

22 {

23 int cap;

24 cout << "Enter capacity of this super array: ";

25 cin >> cap;

26 PFArrayDBak a(cap);

27 cout << "Enter up to " << cap << " nonnegative numbers.\n";

28 cout << "Place a negative number at the end.\n";

29 double next;

30 cin >> next;

31 while ((next >= 0) && (!a.full( )))

33 a.addElement(next);

34 cin >> next;

36 if (next >= 0)

38 cout << "Could not read all numbers.\n";

39 //Clear the unread input:

40 while (next >= 0)

41 cin >> next;

43 int count = a.getNumberUsed( );

44 cout << "The following " << count

45 << " numbers read and stored:\n";

46 int index;

47 for (index = 0; index < count; index++)

48 cout << a[index] << " ";

49 cout << endl;

50 cout << "Backing up array.\n";

51 a.backup( );

52 cout << "Emptying array.\n";

Trang 10

Display 14.12 Demonstration Program for the Class PFArrayDBak (part 3 of 3)

53 a.emptyArray( );

54 cout << a.getNumberUsed( )

55 << " numbers are now stored in the array.\n";

56 cout << "Restoring array.\n";

57 a.restore( );

58 count = a.getNumberUsed( );

59 cout << "The following " << count

60 << " numbers are now stored:\n";

61 for (index = 0; index < count; index++)

62 cout << a[index] << " ";

63 cout << endl;

64 }

SAMPLE DIALOGUE

This program tests the class PFArrayDBak

Enter capacity of this super array: 10

Enter up to 10 nonnegative numbers

Place a negative number at the end

1 2 3 4 5 -1

The following 5 numbers read and stored:

1 2 3 4 5

Backing up array

Emptying array

0 numbers are now stored in the array

Restoring array

The following 5 numbers are now stored:

1 2 3 4 5

Test again? (y/n) y

Enter capacity of this super array: 5

Enter up to 5 nonnegative numbers

Place a negative number at the end

1 2 3 4 5 6 7 -1

Could not read all numbers

The following 5 numbers read and stored:

1 2 3 4 5

Backing up array

Emptying array

0 numbers are now stored in the array

Restoring array

The following 5 numbers are now stored:

Ngày đăng: 04/07/2014, 05:21

TỪ KHÓA LIÊN QUAN

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN