CS 112 - Week 14 Lecture 2 - 2022-12-01 TODAY WE WILL: * announcements * quick note about divide-by-zero * adding OVERRIDING to overloading and redefining * discussion of multiple inheritance * prep for next class * weird fun fact: evidentally divide by zero is NOT defined as a C++ exception! ... instead it is a CPU signal that the OS sends to your program signal handler routine that, by default, terminates the program...! ==== another term! OVERRIDING, to join overloading and redefining ==== * (this is also in Savitch Ch. 15) * redefining: for a non-virtual method, you are making an alternate version of an inherited method to essentially replace the inherited version (has the same signature -- same number and types of arguments, same return type) * overloading: for a non-virtual method(?), you are adding and *additional* version of that method, with different number and/or type of arguments; * WHEN a method IS a virtual method, programmers often say a derived class' version of an inherited method intended to replace the inherited method is OVERRIDING the inherited version, instead of redefining it. ...rather a subtle distinction! Savitch suggest maybe this terminology is here because the compiler DOES treat an overridden method different than a redefined method... (the virtual overridden method DOES have the possibility of dynamic binding) ===== a few words on MULTIPLE inheritance! ===== * what do we mean by this? ...we mean a derived class can have MORE than one base class (this is distinct from a class having, say, ancestor classes... Dessert -> Pie -> CustardPie is not multiple inheritance ParentA ParentB ^ ^ \ / DerivedC THIS is multiple inheritance -- DerivedC has TWO base classes, ParentA and ParentB * the syntax is simple: class DerivedC: public ParentA, public ParentB (some of the implications and complications are not simple, but the syntax is...!) * attempt at some examples where this be useful: class Mammal ... class WingedAnimal ... class Bat: public Mammal, public WingedAnimal ... ===== class Scanner ... class Printer ... class Copier: public Scanner, public Printer ... ==== a few details related to multiple inheritance ==== * the constructors of a derived class derived from multiple base classes are called in the same order in which they are inheritedx (in which they appear in the class definition header) class Bat: public Mammal, public WingedAnimal ... constructor for Mammal will be called, then constructor for WingedAnimal will be called * the destructors are called in REVERSE order of the constructors (so, first WingedAnimal's destructor, then Mammal's destructor) ===== ISSUES with multiple inheritance ===== * so if both parents have a common public method, you'll get a compiler error if you just call that method for the derived class -- it will complain about AMBIGUITY!! * you can get around that by explicitly specifying which parent's you wish to call, for each call! DesiredParent::common_method_name * a bigger classic problem: the diamond problem * can occur when you have a derived class with multiple parents, but some of those parents are themselves derived classes of a common base class class Person .... class Student: public Person .... class Faculty: public Person .... class TA: public Student, public Faculty .... ==== WHAT IF, as another example: class PoweredDevice ... class Scanner: public PoweredDevice ... class Printer: public PoweredDevice ... class Copier: public Scanner, public Printer ... * yikes -- a TA object would try to call the Person constructor twice! -- two copies of all members of Person; and when that TA passes out of scope, Person's destructor would end up being called twice; * SOLUTION? a slightly different use of the virtual keyword! You can declare a class as a VIRTUAL base class for another class by putting virtual before public for that class: class Faculty: virtual public Person ... // Faculty now has Person as a virtual base class. class Student: virtual public Person ... // Student now has Person as a virtual base class. ===== abstract class ===== * a class in C++ is an ABSTRACT class if it has at least one PURE virtual method * what's a pure virtual method? a pure virtual method has NO implementation. * If a derived class is derived from an abstract base class, it EITHER must implement every pure virtual method OR it will also be an abstract class * FUN FACT: a abstract class cannot be instantiated (you can't create an instance of it). BUT it can be used as a base class. * SYNTAX for a pure virtual method: in the class DECLARATION (in our case, the .h file) virtual ret_type method_name(param_decls) = 0; virtual double get_perimeter() = 0; * why would we want abstract classes? They are meant to represent general concepts (for example, Shape or Animal etc.) for which you don't want instances, but you WOULD like to use as base classes for more-concrete derived classes you do want instances of (for example, Circle or Dog, etc.) * what about a PURE ABSTRACT class? * A pure abstract class has ONLY abstract methods and NO data fields and NO concrete methods * In general, a pure abstract class is used to define an interface and is intended to be inherited by concrete classes. It's a way of forcing a kind of contract between the class designer and users of that class