Polymorphism and Virtual Functions in C++

15-1
Chapter 15
Polymorphism and Virtual Functions
15-2
15.1  Type Compatibility in Inheritance Hierarchies
15.2  Polymorphism and Virtual Member Functions
15.3  Abstract Base Classes and Pure Virtual Functions
15.4  Composition Versus Inheritance
15.1 Type Compatibility in Inheritance
Hierarchies
 Classes in a program
   may be part of an
   inheritance hierarchy
 Classes lower in the
  hierarchy are special
  cases of those above
15-3
 
 
 
 
Type Compatibility in Inheritance
A pointer to a derived class can be assigned to a
pointer to a base class.
Another way to say this is:
 
A base class pointer can point to derived class
 
objects
        
Animal *pA
 
=
 
new Cat;
1-4
Type Compatibility in Inheritance
Assigning a base class pointer to a derived class
pointer requires a cast
  Animal *pA = new Cat;
  Cat *pC;
  pC = static_cast<Cat *>(pA);
The base class pointer must already point to a
derived class object for this to work correctly.
1-5
Using Type Casts with Base Class Pointers
C++ uses the declared type of a pointer to determine
access to the members of the pointed-to object
If an object of a derived class is pointed to by a base
class pointer, all members of the derived class may not
be accessible
Type cast the base class pointer to the derived class (via
static_cast
) in order to access members that are
specific to the derived class
1-6
Pointers, Inheritance, and
Overridden Functions
If
a derived class overrides a member function in the
base class, and
a base class pointer points to a derived class object,
then
the compiler determines the version of the function to
use by the type of the pointer, not by the type of the
object.
1-7
Pointers, Inheritance, and
Overridden Functions
(See inheritance4 code posted on Canvas – this is from the main() function)
vector<shared_ptr<Person>> people { 
 
// vector of Person pointers
     
// Person is the base class
   make_shared<TFaculty>("Indiana Jones", Discipline::ARCHEOLOGY,
                         "Dr."),
   make_shared<Student>("Thomas Cruise", Discipline::COMPUTER_SCIENCE,
                        nullptr),
   make_shared<Faculty>("James Stock", Discipline::BIOLOGY),
   make_shared<TFaculty>("Sharon Rock", Discipline::BIOLOGY,
                         "Professor"),
   make_shared<TFaculty>("Nicole Eweman", Discipline::ARCHEOLOGY,
                         "Dr.")
};
// Print the names of the Person objects
for (int k = 0; k < people.size(); k++) {
   cout << people[k]->getName() << endl;   
 
// getName() not virtual
}
     
// so uses base class getName()
     
// function because the pointers
     
// are base class pointers
i1-8
15.2  Polymorphism and Virtual Member
Functions
Polymorphic code
: Code that behaves differently when
it acts on objects of different types
Virtual Member Function
: The C++ mechanism for
achieving polymorphism
1-9
Polymorphism
Consider the Animal,
Cat, Dog hierarchy
where each class has its
own version of the
member function id( )
15-10
 
 
 
 
Polymorphism
class Animal{
  public:
  
void
 
id(){cout
 
<<
 
"animal";}
}
class Cat : public Animal{
  public:
  
void id(){cout << "cat";}
}
class Dog : public Animal{
  public:
  
void id(){cout << "dog";}
}
1-11
Polymorphism
Consider the collection of different Animal
objects
    
Animal *pA[] = {new
 
Animal,
 
new
 
Dog,
                  new
 
Cat};
  
and accompanying code
  
for(int k=0; k<3; k++)
      pA[k]->id();
Prints: 
animal animal animal
, ignoring the
more specific versions of 
id()
 in 
Dog
 and 
Cat
because the pointers are type Animal and the
id() function is not virtual in the Animal class
1-12
Polymorphism
The preceding code is not polymorphic: it behaves
the same way even though 
Animal
, 
Dog
 and 
Cat
have different types and different 
id()
 member
functions
Polymorphic code would have printed "
animal
  
dog
cat"
 instead of "
animal
  
animal
  
animal"
1-13
Polymorphism
The code is NOT polymorphic because in the expression
        
pA[k]->id()
    
the compiler sees only the type of the pointer  
pA[k]
,
which is pointer to  
Animal
Compiler does not see type of actual object pointed to,
which may be  
Animal
, or  
Dog
, or  
Cat
This is called 
static binding
.  At compile time, the
function associated with the pointer type (base class) is
chosen no matter what type of object the pointer is
pointing to.
1-14
Virtual Functions
Declaring a function 
virtual
 will make the compiler
check the type of each object to see if it defines a
more specific version of the virtual function and will
result in 
late binding
, or 
dynamic binding
.
This is where the binding takes place at run-time and
the function chosen is the one associated with the
type of object that the pointer is pointing to.
1-15
Virtual Functions
 
If the member functions
 id() 
are declared virtual, then
the code 
  
Animal *pA[] = {new
 
Animal, new
 
Dog, new
 
Cat};
  for(int k=0; k<3; k++)
      pA[k]->id();
     will print 
 
animal
 
dog
 
cat
1-16
Virtual Functions
How to declare a member function virtual:
class Animal{
  public:
  
virtual
 void id(){cout  <<  "animal";}
}
class Cat : public Animal{
  public:
  
virtual
 void id(){cout << "cat";}
}
class Dog : public Animal{
  public:
  
virtual
 void id(){cout << "dog";}
}
1-17
Function Binding
In  
pA[k]->id()
,
 the compiler must choose
which version of  
id()
 to use: There are
different versions in the  
Animal
, 
Dog
, and 
Cat
classes
Function binding 
is the process of determining
which function definition to use for a particular
function call
static
   and   
dynamic
   binding
1-18
Static Binding
Static binding
 chooses the function in the class
of the base class pointer, ignoring any versions
in the class of the object actually pointed to
Static binding is done at compile time
1-19
Dynamic Binding
Dynamic Binding
 determines the function to be
invoked at execution time
Can look at the actual class of the object pointed
to and choose the most specific version of the
function
Dynamic binding is used to bind virtual functions
1-20
Overriding  vs. Overloading
Recall that  
overloaded
  functions have the
same name but different parameter lists.
If a base class has a virtual member function
and a derived class has an overloading member
function, use the 
override
 key word at the
end of the function header or prototype to
indicate that it should be treated as an
overriding function.
1-21
Overriding  vs. Overloading
Overloading (pr15-04.cpp):
class Base {
  public:
    virtual void functionA(
int
 arg) const
       { cout << "This is Base::functionA" << endl; }
};
class Derived : public Base {
  public:
    virtual void functionA(
long
 arg) const
       { cout << "This is Derived::functionA" << endl; }
};
1-22
Overriding  vs. Overloading
Overriding (pr15-05.cpp):
class Base {
  public:
    virtual void functionA(
int
 arg) const
       { cout << "This is Base::functionA" << endl; }
};
class Derived : public Base {
  public:
    virtual void functionA(
int
 arg) const 
override
       { cout << "This is Derived::functionA" << endl; }
};
1-23
The 
final
 Key Word and Overriding
The key word  
final
  can be used at the end of
the header or prototype of a function in an
inheritance hierarchy if you want to ensure that
no classes below this one override this function.
   
virtual void message() const final;
If an attempt is made to override this function in
a derived class, a compiler error will occur.
1-24
15.3 Abstract Base Classes and Pure Virtual
Functions
An 
abstract class
 is a class that contains no
objects that are not members of subclasses
(derived classes)
For example, in real life, Animal is an abstract
class: there are no animals that are not dogs, or
cats, or lions…
1-25
Abstract Base Classes and Pure Virtual Functions
Abstract classes are an organizational tool.  They
are useful in organizing inheritance hierarchies
Abstract classes can be used to specify an
interface that must be implemented by all
subclasses
1-26
Abstract Functions
The member functions specified in an abstract
class do not have to be implemented
The implementation is left to the subclasses
In C++, an 
abstract class
 is a class with at least
one abstract member function
1-27
Pure Virtual Functions
In C++, a member function of a class is declared to
be an abstract function by making it virtual and
replacing its body with  
= 0;
    
class Animal{
      public:
       
virtual void id() = 0;
    };
A virtual function with its body omitted and
replaced with  
= 0;
  is called a 
pure virtual
function
, or an 
abstract function
1-28
Abstract Classes
An abstract class can not be instantiated
An abstract class can only be inherited from;
that is, you can derive classes from it
Classes derived from abstract classes must
override all pure virtual functions with
concrete member functions before they can
be instantiated
1-29
Abstract Classes
class Shape {
   protected:
      int posX, posY;
   public:
      
virtual void draw() const = 0;
      void setPosition(int pX, int pY) {
         posX = pX;
         posY = pY;
      }
};
class Rectangle : public Shape {
   public:
      
virtual void draw() const 
{
         cout << "Drawing rectangle at " << posX << "  ” << posY << endl;
      }
};
class Hexagon : public Shape {
   public:
      
virtual void draw() const 
{
         cout << "Drawing hexagon at " << posX << "  ” << posY << endl;
      }
};
1-30
Abstract Classes
int main(){
    // Create vector of pointers to Shapes of various types
    vector<shared_ptr<Shape>> shapes  {
          make_shared<Hexagon>(),
          make_shared<Rectangle>(),
          make_shared<Hexagon>()
    };
    // Set positions of all the shapes
    int posX = 5, posY = 15;
    for (int k = 0; k < shapes.size(); k++) {
        shapes[k]->setPosition(posX, posY);
        posX += 10;
        posY += 10;
    };
    // Draw all the shapes at their positions
    for (int j = 0; j < shapes.size(); j++) {
        
shapes[j]->
draw()
;
    }
    return 0;
}
1-31
15.4 Composition vs. Inheritance
Inheritance models an 'is a' relation between
classes.  An object of a derived class 'is a(n)'
object of the base class
Example:
an  
UnderGrad
  is a  
Student
a  
Mammal
 is an  
Animal
a
 
Poodle
 
is a
 
Dog
1-32
Composition vs. Inheritance
When defining a new class:
Composition 
is appropriate when the new class
needs to use an object of an existing class
Inheritance
 is appropriate when
objects of the new class are a subset of the
objects of the existing class, or
objects of the new class will be used in the
same ways as the objects of the existing class
1-33
Composition vs. Inheritance
Inheritance (pr15-07.cpp):
// Base class
class Dog {
   protected:
      double weight;
   public:
      Dog(double w) { weight = w; }
      virtual void bark() const {
          cout << "I am a dog weighing ” << weight << " pounds."
               << endl;
      }
};
// A SheepDog is a special type of Dog
class SheepDog : public Dog {
      int numberSheep;
   public:
      SheepDog(double w, int nSheep) : Dog(w) { numberSheep = nSheep; }
      void bark() const override {
          cout << "I am a sheepdog weighing ” << weight
               << " pounds \n   and guarding ” << numberSheep
               << " sheep." << endl;
      }
};
1-34
Slide Note

Embed
Share

Polymorphism and virtual functions play a key role in C++ programming, allowing for flexibility and extensibility in code through type compatibility, type casts, pointers, inheritance, and overridden functions. By leveraging these concepts, developers can create efficient and maintainable code structures that support complex inheritance hierarchies and facilitate code reusability.

  • C++
  • Polymorphism
  • Virtual functions
  • Inheritance
  • Pointers

Uploaded on Sep 29, 2024 | 1 Views


Download Presentation

Please find below an Image/Link to download the presentation.

The content on the website is provided AS IS for your information and personal use only. It may not be sold, licensed, or shared on other websites without obtaining consent from the author.If you encounter any issues during the download, it is possible that the publisher has removed the file from their server.

You are allowed to download the files provided on this website for personal or commercial use, subject to the condition that they are used lawfully. All files are the property of their respective owners.

The content on the website is provided AS IS for your information and personal use only. It may not be sold, licensed, or shared on other websites without obtaining consent from the author.

E N D

Presentation Transcript


  1. Chapter 15 Polymorphism and Virtual Functions 15-1

  2. 15.1 Type Compatibility in Inheritance Hierarchies 15.2 Polymorphism and Virtual Member Functions 15.3 Abstract Base Classes and Pure Virtual Functions 15.4 Composition Versus Inheritance 15-2

  3. 15.1 Type Compatibility in Inheritance Hierarchies Classes in a program may be part of an inheritance hierarchy Animal Cat Dog Classes lower in the hierarchy are special cases of those above Poodle 15-3

  4. Type Compatibility in Inheritance A pointer to a derived class can be assigned to a pointer to a base class. Another way to say this is: A base class pointer can point to derived class objects Animal *pA = new Cat; 1-4

  5. Type Compatibility in Inheritance Assigning a base class pointer to a derived class pointer requires a cast Animal *pA = new Cat; Cat *pC; pC = static_cast<Cat *>(pA); The base class pointer must already point to a derived class object for this to work correctly. 1-5

  6. Using Type Casts with Base Class Pointers C++ uses the declared type of a pointer to determine access to the members of the pointed-to object If an object of a derived class is pointed to by a base class pointer, all members of the derived class may not be accessible Type cast the base class pointer to the derived class (via static_cast) in order to access members that are specific to the derived class 1-6

  7. Pointers, Inheritance, and Overridden Functions If a derived class overrides a member function in the base class, and a base class pointer points to a derived class object, then the compiler determines the version of the function to use by the type of the pointer, not by the type of the object. 1-7

  8. Pointers, Inheritance, and Overridden Functions (See inheritance4 code posted on Canvas this is from the main() function) vector<shared_ptr<Person>> people { make_shared<TFaculty>("Indiana Jones", Discipline::ARCHEOLOGY, "Dr."), make_shared<Student>("Thomas Cruise", Discipline::COMPUTER_SCIENCE, nullptr), make_shared<Faculty>("James Stock", Discipline::BIOLOGY), make_shared<TFaculty>("Sharon Rock", Discipline::BIOLOGY, "Professor"), make_shared<TFaculty>("Nicole Eweman", Discipline::ARCHEOLOGY, "Dr.") }; // vector of Person pointers // Person is the base class // Print the names of the Person objects for (int k = 0; k < people.size(); k++) { cout << people[k]->getName() << endl; } // getName() not virtual // so uses base class getName() // function because the pointers // are base class pointers i1-8

  9. 15.2 Polymorphism and Virtual Member Functions Polymorphic code: Code that behaves differently when it acts on objects of different types Virtual Member Function: The C++ mechanism for achieving polymorphism 1-9

  10. Polymorphism Animal Consider the Animal, Cat, Dog hierarchy where each class has its own version of the member function id( ) Cat Dog Poodle 15-10

  11. Polymorphism class Animal{ public: voidid(){cout<<"animal";} } class Cat : public Animal{ public: void id(){cout << "cat";} } class Dog : public Animal{ public: void id(){cout << "dog";} } 1-11

  12. Polymorphism Consider the collection of different Animal objects Animal *pA[] = {newAnimal,newDog, newCat}; and accompanying code for(int k=0; k<3; k++) pA[k]->id(); Prints: animal animal animal, ignoring the more specific versions of id() in Dog and Cat because the pointers are type Animal and the id() function is not virtual in the Animal class 1-12

  13. Polymorphism The preceding code is not polymorphic: it behaves the same way even though Animal, Dog and Cat have different types and different id() member functions Polymorphic code would have printed "animaldog cat" instead of "animalanimalanimal" 1-13

  14. Polymorphism The code is NOT polymorphic because in the expression pA[k]->id() the compiler sees only the type of the pointer pA[k], which is pointer to Animal Compiler does not see type of actual object pointed to, which may be Animal, or Dog, or Cat This is called static binding. At compile time, the function associated with the pointer type (base class) is chosen no matter what type of object the pointer is pointing to. 1-14

  15. Virtual Functions Declaring a function virtual will make the compiler check the type of each object to see if it defines a more specific version of the virtual function and will result in late binding, or dynamic binding. This is where the binding takes place at run-time and the function chosen is the one associated with the type of object that the pointer is pointing to. 1-15

  16. Virtual Functions If the member functions id() are declared virtual, then the code Animal *pA[] = {newAnimal, newDog, newCat}; for(int k=0; k<3; k++) pA[k]->id(); will print animaldogcat 1-16

  17. Virtual Functions How to declare a member function virtual: class Animal{ public: virtual void id(){cout << "animal";} } class Cat : public Animal{ public: virtual void id(){cout << "cat";} } class Dog : public Animal{ public: virtual void id(){cout << "dog";} } 1-17

  18. Function Binding In pA[k]->id(), the compiler must choose which version of id() to use: There are different versions in the Animal, Dog, and Cat classes Function binding is the process of determining which function definition to use for a particular function call static and dynamic binding 1-18

  19. Static Binding Static binding chooses the function in the class of the base class pointer, ignoring any versions in the class of the object actually pointed to Static binding is done at compile time 1-19

  20. Dynamic Binding Dynamic Binding determines the function to be invoked at execution time Can look at the actual class of the object pointed to and choose the most specific version of the function Dynamic binding is used to bind virtual functions 1-20

  21. Overriding vs. Overloading Recall that overloaded functions have the same name but different parameter lists. If a base class has a virtual member function and a derived class has an overloading member function, use the override key word at the end of the function header or prototype to indicate that it should be treated as an overriding function. 1-21

  22. Overriding vs. Overloading Overloading (pr15-04.cpp): class Base { public: virtual void functionA(int arg) const { cout << "This is Base::functionA" << endl; } }; class Derived : public Base { public: virtual void functionA(long arg) const { cout << "This is Derived::functionA" << endl; } }; 1-22

  23. Overriding vs. Overloading Overriding (pr15-05.cpp): class Base { public: virtual void functionA(int arg) const { cout << "This is Base::functionA" << endl; } }; class Derived : public Base { public: virtual void functionA(int arg) const override { cout << "This is Derived::functionA" << endl; } }; 1-23

  24. The final Key Word and Overriding The key word final can be used at the end of the header or prototype of a function in an inheritance hierarchy if you want to ensure that no classes below this one override this function. virtual void message() const final; If an attempt is made to override this function in a derived class, a compiler error will occur. 1-24

  25. 15.3 Abstract Base Classes and Pure Virtual Functions An abstract class is a class that contains no objects that are not members of subclasses (derived classes) For example, in real life, Animal is an abstract class: there are no animals that are not dogs, or cats, or lions 1-25

  26. Abstract Base Classes and Pure Virtual Functions Abstract classes are an organizational tool. They are useful in organizing inheritance hierarchies Abstract classes can be used to specify an interface that must be implemented by all subclasses 1-26

  27. Abstract Functions The member functions specified in an abstract class do not have to be implemented The implementation is left to the subclasses In C++, an abstract class is a class with at least one abstract member function 1-27

  28. Pure Virtual Functions In C++, a member function of a class is declared to be an abstract function by making it virtual and replacing its body with = 0; class Animal{ public: virtual void id() = 0; }; A virtual function with its body omitted and replaced with = 0; is called a pure virtual function, or an abstract function 1-28

  29. Abstract Classes An abstract class can not be instantiated An abstract class can only be inherited from; that is, you can derive classes from it Classes derived from abstract classes must override all pure virtual functions with concrete member functions before they can be instantiated 1-29

  30. Abstract Classes class Shape { protected: int posX, posY; public: virtual void draw() const = 0; void setPosition(int pX, int pY) { posX = pX; posY = pY; } }; class Rectangle : public Shape { public: virtual void draw() const { cout << "Drawing rectangle at " << posX << " << posY << endl; } }; class Hexagon : public Shape { public: virtual void draw() const { cout << "Drawing hexagon at " << posX << " << posY << endl; } }; 1-30

  31. Abstract Classes int main(){ // Create vector of pointers to Shapes of various types vector<shared_ptr<Shape>> shapes { make_shared<Hexagon>(), make_shared<Rectangle>(), make_shared<Hexagon>() }; // Set positions of all the shapes int posX = 5, posY = 15; for (int k = 0; k < shapes.size(); k++) { shapes[k]->setPosition(posX, posY); posX += 10; posY += 10; }; // Draw all the shapes at their positions for (int j = 0; j < shapes.size(); j++) { shapes[j]->draw(); } return 0; } 1-31

  32. 15.4 Composition vs. Inheritance Inheritance models an 'is a' relation between classes. An object of a derived class 'is a(n)' object of the base class Example: an UnderGrad is a Student a Mammal is an Animal aPoodleis aDog 1-32

  33. Composition vs. Inheritance When defining a new class: Composition is appropriate when the new class needs to use an object of an existing class Inheritance is appropriate when objects of the new class are a subset of the objects of the existing class, or objects of the new class will be used in the same ways as the objects of the existing class 1-33

  34. Composition vs. Inheritance Inheritance (pr15-07.cpp): // Base class class Dog { protected: double weight; public: Dog(double w) { weight = w; } virtual void bark() const { cout << "I am a dog weighing << weight << " pounds." << endl; } }; // A SheepDog is a special type of Dog class SheepDog : public Dog { int numberSheep; public: SheepDog(double w, int nSheep) : Dog(w) { numberSheep = nSheep; } void bark() const override { cout << "I am a sheepdog weighing << weight << " pounds \n and guarding << numberSheep << " sheep." << endl; } }; 1-34

More Related Content

giItT1WQy@!-/#giItT1WQy@!-/#giItT1WQy@!-/#giItT1WQy@!-/#giItT1WQy@!-/#giItT1WQy@!-/#giItT1WQy@!-/#giItT1WQy@!-/#