Sie sind auf Seite 1von 21

Object Oriented Programming

Lecture #9 Elhanan Borenstein borens@tau.ac.il

copyrights Elhanan Borenstein

Agenda
Permissions and Inheritance Multiple Inheritance Common Ancestor

copyrights Elhanan Borenstein

Permissions and Inheritance

copyrights Elhanan Borenstein

Permissions and Inheritance


The Protect Permission (for class members)
As we recall
A public member in the base class can be accessed by both the derived class and all other (e.g., main). A private member in the base class cannot be accessed by neither the derived class or all other.

There are obviously cases where we wish to deny access from all other classes (and the main), but to allow the derived classes to access this member (part of the family) The protected permission does just that !!!
Base private protected public V V V Derived X V V Other X X V

copyrights Elhanan Borenstein

Permission and Inheritance


Using Permissions in Inheritance
So far all weve learned applies to public inheritance: class derived1: public base Using public inheritance means we do not wish to change the permission of the inherited members:
public members that were inherited are still accessible to everybody protected members that were inherited are still only accessible to derived classes

We can limit these permissions though, by using private and protected inheritance Those limitation will affect only the entities using the derived class (derived class from this class, main, etc.) and not the class itself.
copyrights Elhanan Borenstein

Permissions and Inheritance


Using Permissions in Inheritance - Summary
Base Derived1 : ____ Base Pub Private Protected Public V V V X V(Prt) V(Pub) Prt X V(Prt) V(Prt) Prv X V(Prv) V(Prv) Derived2 : public Derived1 Pub X V(Prt) V(Pub) Prt X V(Prt) V(Prt) Prv X X X Derived1 in Main Pub X X V Prt X X X Prv X X X

copyrights Elhanan Borenstein

Permissions and Inheritance


Permissions in Inheritance Cont
The final permission will always be the more restricting permission (WHY?). Can be used for hiding. An important use for private/protected inheritance is for scenarios where the base class does not implemented enough protection for its members and we wish to fix it. We can restore the original (or an intermediate) permission level (or further restrict the permission) for specific data members by declaring them again (using their full name) under the appropriate permission. Example: prvprt.cpp

copyrights Elhanan Borenstein

Multiple Inheritance

copyrights Elhanan Borenstein

Multiple Inheritance
What have we already learned?

Simple Inheritance
Base

Polymorphism
Base

Derived

Derived1

Derived2

copyrights Elhanan Borenstein

Multiple Inheritance
Introduction
There are cases when we wish to inherit the characteristics of more than one class. That is, we wish to have more than one class as the base class. Inheriting more than one class is permitted in C++. This mechanisms is called: Multiple Inheritance !
(In General, multiple inheritance should be used wisely. There are cases in which we will use other techniques to avoid multiple inheritance.)

class Derived : public Base1, public base2 Base1 Base2


Derived d(); d:
Base1 Members Base2 Members

Derived

Additional
copyrights Elhanan Borenstein

Multiple Inheritance
Guidelines
The same principles of single inheritance, still apply in multiple inheritance:
In case the base class (classes) ctors requires parameters, the derived class should pass these parameters through the initialization line. The derived class can use the methods inherited from the base class, even if they were hidden, using their full names (base::func()). This is particularly useful if there are members with identical names in both base classes (otherwise ambiguity). The derived class can use private members of the base classes through appropriate public methods (get(), set()). While inheriting, the inheritance type (public/protected/private) should be specified for each base class independently.

Example: multiple
copyrights Elhanan Borenstein

Multiple Inheritance
Common Ancestor
As we saw, when members with the same name are inherited by the derived class, we can (and must) access them using their full names. There is, however, an interesting situation where such a scenario is bound to happen. (WHEN?) Ancestor Base1 Ancestor Base2
Base1 a note about drawings Ancestor Base2 Derived

Derived

When both base classes are themselves inherited from a common base (ancestor) class: The members of the common ancestor will appear twice in the Derived class once through Base1 and once through Base2.
copyrights Elhanan Borenstein

Common Ancestor
Why do we actually ends up with duplicated copies? Does it make sense? Ancestor A; A: Ancestor Base1 Ancestor Base2 D: B1:
Ancestor (members)

Base1 B1; Base2 B2;


Ancestor (members) Base1 (additional)

B2:

Ancestor (members) Base2 (additional)

Derived D; Derived
Ancestor (members) Base1 (additional) Ancestor (members) Base2 (additional) Derived (additional) Base1 Base2

copyrights Elhanan Borenstein

Common Ancestor
What is it good for?
A common ancestor inheritance of that sort, is relevant only when the derived entity should, by definition, get two copies of the ancestors members. (Logical argument) Using members which were inherited twice takes place using their full names:
base2::member or base1::member
Members inherited from int m_speed Vehicle (twice): bool m_wings Additional members inherited from Car: x2 bool m_automatic

Example: bat

Additional members int m_missiles inherited from Airplane: Additional members in Batmobile: NONE

copyrights Elhanan Borenstein

Common Ancestor Virtual Inheritance


Virtual Inheritance
In the previous example, all members of the common ancestors appeared twice in the derived class. In most cases, however, this is not the desired behavior (again think of the logical argument). Examples !!! THE MESHURIBUL !
GraphicalItem color Scale GraphicalItem color Scale GraphicalItem color Scale

This is not what we want !!! Here we want the diamond case.
Ancestor Base1 Base2 Derived

Triangle Rectangle

Circle

Meshuribul
copyrights Elhanan Borenstein

Common Ancestor Virtual Inheritance


Virtual Inheritance
If we wish that only one copy of the ancestor members will be inherited we should use: Virtual Inheritance!!! Virtual Inheritance instructs the compiler to use the same location in memory for both copies of the ancestors members.
Each base class will include a pointer to that location. The location (and access) of these members is transparent to the programmer. Only one copy of these member exists. The last assignment (regardless of which base class was used) will determine its value.

copyrights Elhanan Borenstein

Common Ancestor
Simple Inheritance
Ancestor A; A: B1:
Ancestor (members)

Virtual Inheritance
Ancestor A; A:
Ancestor (members) near ptr Base1 (additional) near ptr Base2 (additional) Ancestor (members)

Base1 B1; Base2 B2;


Ancestor (members) Base1 (additional)

Base1 B1; Base2 B2; B1: B2:

B2:

Ancestor (members) Base2 (additional)

Derived D; D:
Ancestor (members) Base1 (additional) Ancestor (members) Base2 (additional) Derived (additional) Base1 Base2

Ancestor (members)

Derived D; D:
near ptr Base1 (additional) near ptr Base2 (additional) Derived (additional) Ancestor (members)

copyrights Elhanan Borenstein

Common Ancestor Virtual Inheritance


Virtual Inheritance
Using Virtual common ancestor is relevant when the ancestors member actually represents the same entity (and should thus appear only once. (Logical argument) Example: vir_inh.cpp

copyrights Elhanan Borenstein

Common Ancestor Virtual Inheritance


Virtual Inheritance
Example: crisis Very Important Notes:
We use the initialization line of ManagerSecretary to send the ctor parameters of Employee. (WHY?) When using virtual inheritance, the common base class must implement a virtual dtor (even if it is empty). Otherwise, we may crash (WHY?) Employee* pe = new Manager() delete pe;

copyrights Elhanan Borenstein

Common Ancestor Virtual Inheritance


One more thing to think about
class Employee { ... void Print() { cout<<"Name:"<<Name<<endl; cout<<"Salary:"<<Salary<<endl; } }; class Manager : virtual public Employee { ... void Print() { Employee::Print(); cout<<"Level:"<<Level<<endl; } }; class Secretary : virtual public Employee { ... void Print() { Employee::Print(); cout<<"Words per min:"<<WordsPerMin<<endl; } }; class ManagerSecretary : public Manager, public Secretary { ... void Print() { Manager::Print(); Secretary::Print(); } };
copyrights Elhanan Borenstein

Questions?

copyrights Elhanan Borenstein

Das könnte Ihnen auch gefallen