15.13 PROTECTED AND PRIVATE DERIVED CLASSES IN C


15.13 PROTECTED AND PRIVATE DERIVED CLASSES IN C++

In all the example of C++ derived classes we have shown so far, the base class was extended through a public derivation, as in

      class Derived_class : public Base_class {        //...      }; 

All of the discussion we have had so far about inheritance and how polymorphism works applies to this situation. This type of inheritance is also referred to as type inheritance. This is the kind of inheritance that is needed for defining subtypes of a type.

There are two other kinds of class derivations that are permissible in C++: private and protected. A private derivation, created by syntax of the form

       class Derived_class : private Base_class {         //...       }; 

results in what's referred to as implementation inheritance. This name reflects the fact that this kind of derivation is good primarily for using locally the public and the protected interface of the base class, but not for making this inherited interface available to other classes, or even to further derived classes. A special case of the implementation inheritance is the protected inheritance obtained by a protected derivation, as in

     class Derived_class : protected Base_class {       //...     }; 

Now the public and the protected interface inherited from the base class is made available for inheritance to the subclasses of the Derived_class.

Before we show an example of implementation inheritance, it needs to be emphasized that when you do not carry out a public derivation, you can no longer assign a Derived* to a Base* without explicit conversion. For example, in our Employee–Manager example, if we had derived Manager using the following syntax

      class Manager : protected Employee {        // same as before      }; 

we would no longer be allowed to say

      Employee* e3 = new Manager( "ms", "importante" ); 

because a Manager is no longer automatically an Employee. Now if we wish to make a single list, in the form of a vector, of Employee* types, we must first use explicit conversion as in

      Employee* e3 = (Employee*) new Manager("ms", "importante"); 

But then, if a Manager was meant to be an Employee, it would be an error to carry out a protected or a private derivation of Manager from Employee.

Let's now try to gain a deeper understanding of what is meant by private and protected class derivations. In the following example, Manager is a subtype of Employee, and Director is a subtype of Manager. At the same time, Manager has a private inheritance from the class ExecutiveRole. We can visualize the hierarchy in the manner shown in Figure 15.11 where solid lines indicate public derivations (and therefore type inheritance) and the dashed line a private inheritance (and therefore an implementation inheritance). The following rather trivial definition of the class ExecutiveRole will suffice for our example:

click to expand
Figure 15.11

      class ExecutiveRole {      public:          void sayExecutiveHello() {              cout << "Hello from Executive ranks" << endl;          }      }; 

The private inheritance allows the Manager class to treat the public interface of ExecutiveRole as a private interface. In other words, the class Manager has full access to the nonprivate section of ExecutiveRole, but Manager treats this inheritance as if it belonged to its private section. What that implies is that this interface inherited from ExecutiveRole is not made available to any other classes, including any derived from Manager.

That should explain the reason why the following program does not compile if we use the commented out line for the header of the class definition of Manager—that is, if it says ‘private’ in the derivation of Manager from ExecutiveRole. The reason for not compiling in that case is the function sayExecutiveHello() that is invoked in the Director class in line (B). Note that there is no problem accessing sayExecutiveHello() in the Manager class itself in line (A), but the function is not inherited by the Director class if Manager has a private derivation from ExecutiveRole.

On the other hand, the program runs fine as shown—that is, when Manager has a protected derivation from the ExecutiveRole class. In a protected derivation, the public interface of a base class is made available to other classes that may be derived from the class in question. In our example, when Manager has a protected derivation from ExecutiveRole, the function sayExecutiveHello() becomes visible in the Director class.

 
//ImplementationInherit . cc #include <iostream> #include <string> #include <vector> using namespace std; class Employee { string firstName, lastName; int age, yearsInService; public: Employee (string fnam, string lnam) : firstName (fnam), lastName (lnam) {} virtual void print () const { cout << firstName << " " << lastName << endl; } void sayEmployeeHello() { cout << "hello from Employee class" << endl; } }; class ExecutiveRole { public: void sayExecutiveHello() { cout << "Hello from Executive ranks" << endl; } }; //class Manager // : public Employee, private ExecutiveRole { // WILL NOT COMPILE class Manager : public Employee, protected ExecutiveRole { // WORKS FINE short level; public: Manager (string fnam, string lnam, short lvl) : Employee (fnam, lnam), level (1v1) { cout<< "In Manager constructor: "; sayEmployeeHello(); sayExecutiveHello(); //(A) } void print () const { Employee::print(); cout << "level: " << level << endl; } }; class Director : public Manager { short grade; public: Director (string fnam, string lnam, short lvl, short gd) :Manager (fnam , lnam, lvl), grade (gd) { cout << "In Director constructor: "; sayEmployeeHello(); sayExecutiveHello(); //(B) } void print () const { Manager:: print(); cout << "grade: " << grade << endl << endl; } }; int main(){ vector<Employee*> empList; Employee* e1 = new Employee("joe", "schmoe"); Employee* e2 = (Employee*) new Manager( "ms", "importante", 2); Employee* e3 = (Employee*) new Director ("mister", "bigshot", 3, 4); //(C) empList.push_back(e1); empList.push_back(e2); empList.push_back(e3); vector<Employee*>:: iterator p = empList. begin (); while (p < empList.end() )(*p++)->print(); Manager* m = new Manager("jane", "doe", 2); m->sayEmployeeHello(); Director* d = new Director("john", "doe", 3, 4); d->sayEmployeeHello (); return 0; }

As we will discuss in the next chapter, a C++ class can have multiple superclasses. A C++class is allowed to have different derivation types with respect to each of its base classes, That is, a class may have public derivation with respect to some of its base classes, private derivation with respect to some others, and a protected derivation with respect to the rest.




Programming With Objects[c] A Comparative Presentation of Object-Oriented Programming With C++ and Java
Programming with Objects: A Comparative Presentation of Object Oriented Programming with C++ and Java
ISBN: 0471268526
EAN: 2147483647
Year: 2005
Pages: 273
Authors: Avinash Kak

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net