12.3.3. Derived-Class Member-Function Calls via Base-Class Pointers

Off a base-class pointer, the compiler allows us to invoke only base-class member functions. Thus, if a base-class pointer is aimed at a derived-class object, and an attempt is made to access a derived-class-only member function, a compilation error will occur.

Figure 12.3 shows the consequences of attempting to invoke a derived-class member function off a base-class pointer. [Note: We’re again reusing the versions of classes CommissionEmployee and BasePlusCommissionEmployee from Section 11.3.5.] Line 11 creates commissionEmployeePtr—a pointer to a CommissionEmployee object—and lines 12–13 create a BasePlusCommissionEmployee object. Line 16 aims the base-class commissionEmployeePtr at derived-class object basePlusCommissionEmployee. Recall from Section 12.3.1 that this is allowed, because a BasePlusCommissionEmployee is a CommissionEmployee (in the sense that a BasePlusCommissionEmployee object contains all the functionality of a CommissionEmployee object). Lines 20–24 invoke base-class member functions getFirstName, getLastName, getSocialSecurityNumber, getGrossSales and getCommissionRate off the base-class pointer. All of these calls are allowed, because BasePlusCommissionEmployee inherits these member functions from CommissionEmployee. We know that commissionEmployeePtr is aimed at a BasePlusCommissionEmployee object, so in lines 28–29 we attempt to invoke BasePlusCommissionEmployee member functions getBaseSalary and setBaseSalary. The compiler generates errors on both of these calls, because they’re not made to member functions of base-class CommissionEmployee. The handle can be used to invoke only those functions that are members of that handle’s associated class type. (In this case, off a CommissionEmployee *, we can invoke only CommissionEmployee member functions setFirstName, getFirstName, setLastName, getLastName, setSocialSecurityNumber, getSocialSecurityNumber, setGrossSales, getGrossSales, setCommissionRate, getCommissionRate, earnings and print.)


 1   // Fig. 12.3: fig12_03.cpp
 2   // Attempting to invoke derived-class-only member functions
 3   // via a base-class pointer.
 4   #include <string>
 5   #include "CommissionEmployee.h"
 6   #include "BasePlusCommissionEmployee.h"
 7   using namespace std;
 8
 9   int main()
10   {
11      CommissionEmployee *commissionEmployeePtr = nullptr; // base class ptr
12      BasePlusCommissionEmployee basePlusCommissionEmployee(
13         "Bob", "Lewis", "333-33-3333", 5000, .04, 300 ); // derived class
14
15      // aim base-class pointer at derived-class object (allowed)
16      commissionEmployeePtr = &basePlusCommissionEmployee;
17
18      // invoke base-class member functions on derived-class
19      // object through base-class pointer (allowed)
20      string firstName = commissionEmployeePtr->getFirstName();
21      string lastName = commissionEmployeePtr->getLastName();
22      string ssn = commissionEmployeePtr->getSocialSecurityNumber();
23      double grossSales = commissionEmployeePtr->getGrossSales();
24      double commissionRate = commissionEmployeePtr->getCommissionRate();
25
26      // attempt to invoke derived-class-only member functions          
27      // on derived-class object through base-class pointer (disallowed)
28      double baseSalary = commissionEmployeePtr->getBaseSalary();       
29      commissionEmployeePtr->setBaseSalary( 500 );                      
30   } // end main

GNU C++ compiler error messages:


fig12_03.cpp:28:47: error: 'class CommissionEmployee' has no member named
   'getBaseSalary'
fig12_03.cpp:29:27: error: 'class CommissionEmployee' has no member named
   'setBaseSalary'


Fig. 12.3. Attempting to invoke derived-class-only functions via a base-class pointer.

Downcasting

The compiler will allow access to derived-class-only members from a base-class pointer that’s aimed at a derived-class object if we explicitly cast the base-class pointer to a derived-class pointer—this is known as downcasting. As you know, it’s possible to aim a base-class pointer at a derived-class object. However, as we demonstrated in Fig. 12.3, a base-class pointer can be used to invoke only the functions declared in the base class. Downcasting allows a derived-class-specific operation on a derived-class object pointed to by a base-class pointer. After a downcast, the program can invoke derived-class functions that are not in the base class. Downcasting is a potentially dangerous operation. Section 12.8 demonstrates how to safely use downcasting.


Image Software Engineering Observation 12.3

If the address of a derived-class object has been assigned to a pointer of one of its direct or indirect base classes, it’s acceptable to cast that base-class pointer back to a pointer of the derived-class type. In fact, this must be done to call derived-class member functions that do not appear in the base class.


..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset