Define a Class Derived from the string Class

  • Slides: 21
Download presentation
Define a Class Derived from the string Class #include <iostream> #include <string> using std:

Define a Class Derived from the string Class #include <iostream> #include <string> using std: : cout; using std: : string; class CString : public string { public: CString(string s): string(s) {} }; int main() { CString my. String("This is a test. "); cout << my. String. length() << 'n'; return 0; } 1

#include <iostream> #include <string> using std: : cout; using std: : string; class CString

#include <iostream> #include <string> using std: : cout; using std: : string; class CString : public string { public: CString(string s): string(s) {} CString toupper() { CString temp = ""; for (int i=0; i< this->length(); i++) { char c = this->at(i); if (c >= 'a' && c <= 'z') c -=32; temp = temp + c; } return temp; } }; int main() { CString my. String("This is a test. "); cout << my. String. length() << 'n'; cout << my. String. toupper() << 'n'; return 0; } 2

Exercise p Define a To. Upper() function for your CString class, which will convert

Exercise p Define a To. Upper() function for your CString class, which will convert the first character of every word to uppercase. n e. g. “This is a test. ” -> “This Is A Test. ” 3

Chapter 9 Class Inheritance and Virtual Functions 4

Chapter 9 Class Inheritance and Virtual Functions 4

Virtual Functions p p Let us look closely at inherited member functions. Box. h

Virtual Functions p p Let us look closely at inherited member functions. Box. h in P. 572 n n Volume() – Calculate the volume of a CBox object Show. Volume() - Output the volume of a CBox object CBox() – The constructor sets the data member values in the initialization list : m_Length(lv), m_Width(wv), m_Height(hv) so no statements are necessary in the body of the function. Data members are specified as protected, so they are accessible to the member functions of any derived class. 5

Glass. Box. h Suppose we need a different kind of box to hold glassware.

Glass. Box. h Suppose we need a different kind of box to hold glassware. p The contents would be fragile. p n n Some packaging material is added to protect them, so the capacity of the box is less than the capacity of a basic CBox object. You need a different Volume() function to calculate the volume. Glass. Box. h in P. 573 p return 0. 85*m_Length*m_Width*m_Height; p 6

Ex 9_06. cpp Try It Out int main() { CBox my. Box(2. 0, 3.

Ex 9_06. cpp Try It Out int main() { CBox my. Box(2. 0, 3. 0, 4. 0); // Declare a base box CGlass. Box my. Glass. Box(2. 0, 3. 0, 4. 0); // Declare derived box same size p my. Box. Show. Volume(); my. Glass. Box. Show. Volume(); // Display volume of base box // Display volume of derived box cout << endl; return 0; } p The output is n n CBox usable volume is 24 7

Why Doesn’t It Work? The volume of a CGlass. Box object should be only

Why Doesn’t It Work? The volume of a CGlass. Box object should be only 85% of a CBox with the same dimension. p Reason: p n n n The call of the Volume() function in the function Show. Volume() is being set once and for all by the compiler (as the version defined in the base class). The compiler has no knowledge of any other Volume() function. This is sometimes called early binding. p See the animation in the next page. 8

Figure Indicating Early Binding CBox Volume() CGlass. Box Volume() Show. Volume() my. Box. Show.

Figure Indicating Early Binding CBox Volume() CGlass. Box Volume() Show. Volume() my. Box. Show. Volume() my. Glass. Box. Show. Volume()

What Are We Hoping For? We want the actual version of the function Volume()

What Are We Hoping For? We want the actual version of the function Volume() invoked by Show. Volume() to be determined by the object being processed. p This is sometimes called dynamic linkage, or late binding. p p C++ provides the mechanism of virtual function to support this. 10

Fixing the CGlass. Box p Box. h & Glass. Box. h in P. 575

Fixing the CGlass. Box p Box. h & Glass. Box. h in P. 575 n p The keyword virtual is added to the definitions of the Volume() function in the two classes. The result is what we expected n n CBox usable volume is 24 CBox usable volume is 20. 4 The ability to use virtual functions for late binding is referred to as the mechanism of Polymorphism in Object-Oriented Programming. p Let us see another important technique. p 11

Using Pointers to Class Objects p Pointers to Base and Derived Classes CBox my.

Using Pointers to Class Objects p Pointers to Base and Derived Classes CBox my. Box(2. 0, 3. 0, 4. 0); CGlass. Box my. Glass. Box(2. 0, 3. 0, 4. 0); CBox* p. Box = 0; // Declare a base box // Declare derived box of same size // Declare a pointer to base class objects p. Box = &my. Box; // Set pointer to address of base object p. Box->Show. Volume(); // Display volume of base box p. Box = &my. Glass. Box; // Set pointer to derived class object p. Box->Show. Volume(); // Display volume of derived box cout << endl; return 0; p A pointer to a base class object can be assigned the address of a derived class object as well. 12

Figure 9 -4 (P. 578) Figure 9 -4 13

Figure 9 -4 (P. 578) Figure 9 -4 13

Pure Virtual Functions p Container. h in P. 580 n virtual double Volume() const

Pure Virtual Functions p Container. h in P. 580 n virtual double Volume() const = 0 n This statement declares a pure virtual function. p p Redefined in derived class, but meaningless in the base class. A class containing a pure virtual function is called an abstract class. n n It is called abstract because you cannot define objects of a class containing a pure virtual function. It exists only for the purpose of defining classes that are derived from it. 14

Indirect Base Classes Figure 9 -5 (P. 584) 15

Indirect Base Classes Figure 9 -5 (P. 584) 15

Ex 9_11 p Glass. Box. h in P. 585 n p Box. h in

Ex 9_11 p Glass. Box. h in P. 585 n p Box. h in P. 581 n p Class CBox derived from CContainer Can. h in P. 582 n p It does not define Show. Volume(). Class CCan derived from CContainer Ex 9_11. cpp in P. 585 n n n CBox usable volume is 24 Volume is 45. 9458 CBox usable volume is 20. 4 16

Virtual Destructors One problem of derived classes using a pointer to the base class

Virtual Destructors One problem of derived classes using a pointer to the base class is that, the correct destructor may not be called. p Let us output a message for tracking in the destructor. p n n Container. h in P. 586 Can. h Box. h Glass. Box. h 17

Wrong Destructors Are Called (P. 588) p p p p CBox usable volume is

Wrong Destructors Are Called (P. 588) p p p p CBox usable volume is 24 Delete CBox CContainer destructor called We expect a CBox destructor CBox usable volume is 102 Delete CGlass. Box CContainer destructor called We expect a CGlass. Box destructor Volume is 45. 9458 CBox usable volume is 20. 4 CGlass. Box destructor called CContainer destructor called CCan destructor called CContainer destructor called 18

Correcting the Problem p The reason is that, the compiler only know the pointer

Correcting the Problem p The reason is that, the compiler only know the pointer type is a pointer to the base class CContainer. p We can declare the destructor of the base class to be virtual, so that it will be resolved dynamically. n p P. 589 This solves the problem correctly. 19

Casting Between Class Types p You have seen how to store the address of

Casting Between Class Types p You have seen how to store the address of a CBox object to a variable of type CContainer*. n p How do you store an address of type CContainer* to a variable of type CBox* n p Store the address of a derived class object in a variable of a base class type. CBox* p. Box = dynamic_cast<CBox*>(p. Container); The difference between dynamic_cast and static_cast: n n dynamic_cast operator checks the validity of a cast at run -time, while static_cast operator does not. If a dynamic_cast operation is not valid, the result is null. 20

Exercise p P. 639 n Ex 2, Ex 3 21

Exercise p P. 639 n Ex 2, Ex 3 21