一个关于多态之虚函数的例子

目录(?)[+]

引言

本博文通过包含了一个公司支付系统中各种雇员情况的一个继承层次来讨论基类和派生类之间的关系.佣金雇员(表示为一个基类对象)的薪水完全是销售提成,带底薪佣雇员(表示为一个派生类的对象)的薪水由底薪和销售提成组成.以及创建一个增强的雇员类层次结构,以解决下面的问题:

  • 假设某家公司按周支付雇员工资,雇员一共有有4类:
    • 定薪雇员:不管每周工作多长时间都领取固定的周薪
    • 钟点雇员:按工作的小时数领取工资,并且可以领取超过40个小时之外的加班费
    • 佣金雇员:工资完全是销售业绩提成
    • 带薪佣雇员:工资是基本工资和销售提成组成
  • 在这次工资发放阶级,公司决定奖励带佣金雇员,把他们的基本工资提高10%.公司想实现一个C++程序多态地执行工资的计算.

我们使用抽象类Employee表示通常概念的雇员.直接从Employee类派生的是类SalariedEmployee,CommissionEmployee 和HourlyEmployee.而BasePlusCommissionEmployee类又是从CommissionEmployee类直接派生的,代表最后一种雇员类型.如图1所中的UML图显示多态的雇员工资应用程序中类的继承层次结构.


图1:雇员类型层次结构的UML图

抽象类Employee声明了类层次结构的"接口",即程序可以对所有的Employee类对象调用的一组成员函数集合.每个雇员,不论他的工资计算方式如何,都有名,姓及社会安全号码,因此在抽象基类Employee中含有private数据成员firstName ,lastName和 socialSecurityNumber.接下来的内容将实现上述的Employee类层次结构.在最后构建一个测试程序,它创建所有这些类的对象并多态地处理对象.

创建抽象基类: Employee类

图2给出了图表类继承层次中的5个类,顶部显示的是earnings和print函数名.对于每个类,这张图表显示了每个函数期望的实现.注意在Employee类中earnings函数被指定"=0",表示它是一个纯virtual函数.每个派生类都重写earnings函数,提供合适的实现.

图2:Employee类层次结构的多态性接口

让我们考虑Employee类头文件(如下程序所示).public成员函数包括:一个构造函数,该构造函数以名,姓及社会安全号码为参数;设置函数名,姓及社会安全号码;获取函数,返回了名,姓及社会安全号码;以及纯virtual 函数earnings和virtual函数print;  

Employee类头文件

  1. //  Employee.h: Employee abstract base class.  
  2. #ifndef EMPLOYEE_H  
  3. #define EMPLOYEE_H  
  4.   
  5. #include <string> // C++ standard string class  
  6. using std::string;  
  7.   
  8. class Employee   
  9. {  
  10. public:  
  11.    Employee( const string &, const string &, const string & );  
  12.   
  13.    void setFirstName( const string & ); // set first name  
  14.    string getFirstName() const// return first name  
  15.   
  16.    void setLastName( const string & ); // set last name  
  17.    string getLastName() const// return last name  
  18.   
  19.    void setSocialSecurityNumber( const string & ); // set SSN  
  20.    string getSocialSecurityNumber() const// return SSN  
  21.   
  22.    // pure virtual function makes Employee abstract base class  
  23.    virtual double earnings() const = 0; // pure virtual  
  24.    virtual void print() const// virtual  
  25. private:  
  26.    string firstName;  
  27.    string lastName;  
  28.    string socialSecurityNumber;  
  29. }; // end class Employee  
  30.   
  31. #endif // EMPLOYEE_H  

而 Employee类的实现文件中,没有为纯virtual 函数earnings提供任何实现.请注意: Employee类的构造函数并没有确认社会号码的有效性.通常应提供这类有效性确认.

Employee类的实现文件

  1. //  Employee.cpp: Abstract-base-class Employee member-function definitions.  
  2. // Note: No definitions are given for pure virtual functions.  
  3. #include <iostream>  
  4. using std::cout;  
  5.   
  6. #include "Employee.h" // Employee class definition  
  7.   
  8. // constructor  
  9. Employee::Employee( const string &first, const string &last,  
  10.    const string &ssn )  
  11.    : firstName( first ), lastName( last ), socialSecurityNumber( ssn )  
  12. {  
  13.    // empty body   
  14. // end Employee constructor  
  15.   
  16. // set first name  
  17. void Employee::setFirstName( const string &first )   
  18. {   
  19.    firstName = first;    
  20. // end function setFirstName  
  21.   
  22. // return first name  
  23. string Employee::getFirstName() const   
  24. {   
  25.    return firstName;    
  26. // end function getFirstName  
  27.   
  28. // set last name  
  29. void Employee::setLastName( const string &last )  
  30. {  
  31.    lastName = last;     
  32. // end function setLastName  
  33.   
  34. // return last name  
  35. string Employee::getLastName() const  
  36. {  
  37.    return lastName;     
  38. // end function getLastName  
  39.   
  40. // set social security number  
  41. void Employee::setSocialSecurityNumber( const string &ssn )  
  42. {  
  43.    socialSecurityNumber = ssn; // should validate  
  44. // end function setSocialSecurityNumber  
  45.   
  46. // return social security number  
  47. string Employee::getSocialSecurityNumber() const  
  48. {  
  49.    return socialSecurityNumber;     
  50. // end function getSocialSecurityNumber  
  51.   
  52. // print Employee's information  
  53. void Employee::print() const  
  54. {   
  55.    cout << getFirstName() << ' ' << getLastName()   
  56.       << "\nsocial security number: " << getSocialSecurityNumber();   
  57. // end function print  

注意:virtual函数print提供的实现会在每个派生类中被重写.可是,这些print函数都将使用这个抽象类中print函数的版本,输出Employee声明了类层次结构中所有类共有的信息.

创建具体的派生类: SalariedEmployee类

SalariedEmployee类是从Employee类派生而来的,其public成员函数包括:一个以名, 姓,社会安全号码和周薪为参数的构造函数;给数据成员weeklySalary赋一个非负的设置函数;返回weeklySalary值的获取函数;计算一个SalariedEmployee雇员收入的virtual函数earnings;打印雇员信息的virtual函数print,它输出的内容依次是雇员类型(即:"salaried employee").以及由基类Employee的print函数和SalariedEmployee类的 getWeeklySalary函数产生的雇员的特定信息.

SalariedEmployee类头文件

  1. // SalariedEmployee.h: SalariedEmployee class derived from Employee.  
  2. #ifndef SALARIED_H  
  3. #define SALARIED_H  
  4.   
  5. #include "Employee.h" // Employee class definition  
  6.   
  7. class SalariedEmployee : public Employee   
  8. {  
  9. public:  
  10.    SalariedEmployee( const string &, const string &,   
  11.       const string &, double = 0.0 );  
  12.   
  13.    void setWeeklySalary( double ); // set weekly salary  
  14.    double getWeeklySalary() const// return weekly salary  
  15.   
  16.    // keyword virtual signals intent to override  
  17.    virtual double earnings() const// calculate earnings  
  18.    virtual void print() const// print SalariedEmployee object  
  19. private:  
  20.    double weeklySalary; // salary per week  
  21. }; // end class SalariedEmployee  
  22.   
  23. #endif // SALARIED_H  

SalariedEmployee类的成员函数的实现.类的构造函数把名,姓和社会安全号码传递给基类Employee的构造函数,从而对从基类继承但在派行类中不可访问的private数据成员进行了初始化.SalariedEmployee类的print函数重写了基类Employee的print函数.如果SalariedEmployee类不重写print函数,那么SalariedEmployee类将继承基类Employee的print函数.

SalariedEmployee类实现文件

  1. // SalariedEmployee.cpp :SalariedEmployee class member-function definitions.  
  2. #include <iostream>  
  3. using std::cout;  
  4.   
  5. #include "SalariedEmployee.h" // SalariedEmployee class definition  
  6.   
  7. // constructor   
  8. SalariedEmployee::SalariedEmployee( const string &first,   
  9.    const string &last, const string &ssn, double salary )  
  10.    : Employee( first, last, ssn )  
  11. {   
  12.    setWeeklySalary( salary );   
  13. // end SalariedEmployee constructor  
  14.   
  15. // set salary  
  16. void SalariedEmployee::setWeeklySalary( double salary )  
  17. {   
  18.    weeklySalary = ( salary < 0.0 ) ? 0.0 : salary;   
  19. // end function setWeeklySalary  
  20.   
  21. // return salary  
  22. double SalariedEmployee::getWeeklySalary() const  
  23. {  
  24.    return weeklySalary;  
  25. // end function getWeeklySalary  
  26.   
  27. // calculate earnings;   
  28. // override pure virtual function earnings in Employee  
  29. double SalariedEmployee::earnings() const   
  30. {   
  31.    return getWeeklySalary();   
  32. // end function earnings  
  33.   
  34. // print SalariedEmployee's information   
  35. void SalariedEmployee::print() const  
  36. {  
  37.    cout << "salaried employee: ";  
  38.    Employee::print(); // code reuse  
  39.    cout << "\nweekly salary: " << getWeeklySalary();  
  40. // end function print  

创建具体的派生类: HourlyEmployee类

HourlyEmployee类头文件

  1. //  HourlyEmployee.h  
  2. // HourlyEmployee class definition.  
  3. #ifndef HOURLY_H  
  4. #define HOURLY_H  
  5.   
  6. #include "Employee.h" // Employee class definition  
  7.   
  8. class HourlyEmployee : public Employee   
  9. {  
  10. public:  
  11.    HourlyEmployee( const string &, const string &,   
  12.       const string &, double = 0.0, double = 0.0 );  
  13.      
  14.    void setWage( double ); // set hourly wage  
  15.    double getWage() const// return hourly wage  
  16.   
  17.    void setHours( double ); // set hours worked  
  18.    double getHours() const// return hours worked  
  19.   
  20.    // keyword virtual signals intent to override  
  21.    virtual double earnings() const// calculate earnings  
  22.    virtual void print() const// print HourlyEmployee object  
  23. private:  
  24.    double wage; // wage per hour  
  25.    double hours; // hours worked for week  
  26. }; // end class HourlyEmployee  
  27.   
  28. #endif // HOURLY_H  

HourlyEmployee类实现文件

// HourlyEmployee.cpp: HourlyEmployee class member-function definitions.
#include <iostream>
using std::cout;

#include "HourlyEmployee.h" // HourlyEmployee class definition

// constructor
HourlyEmployee::HourlyEmployee(const string &first, const string &last,
	const string &ssn, double hourlyWage, double hoursWorked)
	: Employee(first, last, ssn)
{
	setWage(hourlyWage); // validate hourly wage
	setHours(hoursWorked); // validate hours worked
} // end HourlyEmployee constructor

// set wage
void HourlyEmployee::setWage(double hourlyWage)
{
	wage = hourlyWage < 0.0 ? 0.0 : hourlyWage;
} // end function setWage

// return wage
double HourlyEmployee::getWage() const
{
	return wage;
} // end function getWage

// set hours worked
void HourlyEmployee::setHours(double hoursWorked)
{
	hours = hoursWorked < 0.0 ? 0.0 : hoursWorked;
}
double HourlyEmployee::getHours() const
{
	return hours;
}
double HourlyEmployee::earnings() const
{
	return getWage() * getHours();
}
void HourlyEmployee::print() const
{
	cout << "Hourly employee: ";
	Employee::print(); // code reuse
	cout << "\nwage: " << getWage()
		<< "; hours: " << getHours();
}


创建具体的派生类: CommissionEmployee类

CommissionEmployee类头文件

  1. // CommissionEmployee.h: CommissionEmployee class derived from Employee.  
  2. #ifndef COMMISSION_H  
  3. #define COMMISSION_H  
  4.   
  5. #include "Employee.h" // Employee class definition  
  6.   
  7. class CommissionEmployee : public Employee   
  8. {  
  9. public:  
  10.    CommissionEmployee( const string &, const string &,  
  11.       const string &, double = 0.0, double = 0.0 );  
  12.   
  13.    void setCommissionRate( double ); // set commission rate  
  14.    double getCommissionRate() const// return commission rate  
  15.   
  16.    void setGrossSales( double ); // set gross sales amount  
  17.    double getGrossSales() const// return gross sales amount  
  18.   
  19.    // keyword virtual signals intent to override  
  20.    virtual double earnings() const// calculate earnings  
  21.    virtual void print() const// print CommissionEmployee object  
  22. private:  
  23.    double grossSales; // gross weekly sales  
  24.    double commissionRate; // commission percentage  
  25. }; // end class CommissionEmployee  
  26.   
  27. #endif // COMMISSION_H  

CommissionEmployee类实现文件

  1. // CommissionEmployee.cpp: CommissionEmployee class member-function definitions.  
  2. #include <iostream>  
  3. using std::cout;  
  4.   
  5. #include "CommissionEmployee.h" // CommissionEmployee class definition  
  6.   
  7. // constructor   
  8. CommissionEmployee::CommissionEmployee( const string &first,   
  9.    const string &last, const string &ssn, double sales, double rate )  
  10.    : Employee( first, last, ssn )    
  11. {  
  12.    setGrossSales( sales );  
  13.    setCommissionRate( rate );  
  14. // end CommissionEmployee constructor  
  15.   
  16. // set commission rate  
  17. void CommissionEmployee::setCommissionRate( double rate )  
  18. {   
  19.     commissionRate = ( rate > 0.0 && rate < 1.0 ) ? rate : 0.0;  
  20. // end function setCommissionRate  
  21.   
  22. // return commission rate  
  23. double CommissionEmployee::getCommissionRate() const  
  24. {  
  25.     return commissionRate;  
  26. // end function getCommissionRate  
  27.   
  28. // set gross sales amount  
  29. void CommissionEmployee::setGrossSales( double sales )   
  30. {   
  31.    grossSales = ( sales < 0.0 ) ? 0.0 : sales;   
  32. // end function setGrossSales  
  33.   
  34. // return gross sales amount  
  35. double CommissionEmployee::getGrossSales() const  
  36. {  
  37.     return grossSales;  
  38. // end function getGrossSales  
  39.   
  40. // calculate earnings;  
  41. // override pure virtual function earnings in Employee  
  42. double CommissionEmployee::earnings() const  
  43. {   
  44.    return getCommissionRate() * getGrossSales();   
  45. // end function earnings  
  46.   
  47. // print CommissionEmployee's information   
  48. void CommissionEmployee::print() const  
  49. {  
  50.    cout << "commission employee: ";  
  51.    Employee::print(); // code reuse  
  52.    cout << "\ngross sales: " << getGrossSales()   
  53.       << "; commission rate: " << getCommissionRate();  
  54. // end function print  

创建具体的派生类: BasePlusCommissionEmployee类

BasePlusCommissionEmployee类头文件

  1. // BasePlusCommissionEmployee.h  
  2. // BasePlusCommissionEmployee class derived from Employee.  
  3. #ifndef BASEPLUS_H  
  4. #define BASEPLUS_H  
  5.   
  6. #include "CommissionEmployee.h" // CommissionEmployee class definition  
  7.   
  8. class BasePlusCommissionEmployee : public CommissionEmployee   
  9. {  
  10. public:  
  11.    BasePlusCommissionEmployee( const string &, const string &,  
  12.       const string &, double = 0.0, double = 0.0, double = 0.0 );  
  13.   
  14.    void setBaseSalary( double ); // set base salary  
  15.    double getBaseSalary() const// return base salary  
  16.   
  17.    // keyword virtual signals intent to override  
  18.    virtual double earnings() const// calculate earnings  
  19.    virtual void print() const// print BasePlusCommissionEmployee object  
  20. private:  
  21.    double baseSalary; // base salary per week  
  22. }; // end class BasePlusCommissionEmployee  
  23.   
  24. #endif // BASEPLUS_H  

BasePlusCommissionEmployee类实现文件

  1. // BasePlusCommissionEmployee.cpp: BasePlusCommissionEmployee member-function definitions.  
  2. #include <iostream>  
  3. using std::cout;  
  4.   
  5. // BasePlusCommissionEmployee class definition  
  6. #include "BasePlusCommissionEmployee.h"  
  7.   
  8. // constructor   
  9. BasePlusCommissionEmployee::BasePlusCommissionEmployee(   
  10.    const string &first, const string &last, const string &ssn,   
  11.    double sales, double rate, double salary )  
  12.    : CommissionEmployee( first, last, ssn, sales, rate )    
  13. {  
  14.    setBaseSalary( salary ); // validate and store base salary  
  15. // end BasePlusCommissionEmployee constructor  
  16.   
  17. // set base salary  
  18. void BasePlusCommissionEmployee::setBaseSalary( double salary )  
  19. {   
  20.    baseSalary = ( salary < 0.0 ) ? 0.0 : salary;   
  21. // end function setBaseSalary  
  22.   
  23. // return base salary  
  24. double BasePlusCommissionEmployee::getBaseSalary() const  
  25. {   
  26.     return baseSalary;   
  27. // end function getBaseSalary  
  28.   
  29. // calculate earnings;  
  30. // override pure virtual function earnings in Employee  
  31. double BasePlusCommissionEmployee::earnings() const  
  32. {   
  33.     return getBaseSalary() + CommissionEmployee::earnings();   
  34. // end function earnings  
  35.   
  36. // print BasePlusCommissionEmployee's information   
  37. void BasePlusCommissionEmployee::print() const  
  38. {  
  39.    cout << "base-salaried ";  
  40.    CommissionEmployee::print(); // code reuse  
  41.    cout << "; base salary: " << getBaseSalary();  
  42. // end function print  

演示多态性的执行过程

为了测试Employee类层次结构,如下所示程序中的程序为4个具体类 SalariedEmployee, HourlyEmployee, CommissionEmployee和BasePlusCommissionEmployee的每一个都创建了一个对象.程序首先使用静态绑定方式对这些对象进行了操作,然后使用Employee指针的vector多态地对这些对象进行操作.

Employee类层次结构的驱动程序

  1. // Demonstrating downcasting and run-time type information.  
  2. // NOTE: For this example to run in Visual C++ .NET,   
  3. // you need to enable RTTI (Run-Time Type Info) for the project.  
  4. #include <iostream>  
  5. using std::cout;  
  6. using std::endl;  
  7. using std::fixed;  
  8.   
  9. #include <iomanip>  
  10. using std::setprecision;  
  11.     
  12. #include <vector>  
  13. using std::vector;  
  14.   
  15. #include <typeinfo>  
  16.   
  17. // include definitions of classes in Employee hierarchy  
  18. #include "Employee.h"  
  19. #include "SalariedEmployee.h"   
  20. #include "HourlyEmployee.h"  
  21. #include "CommissionEmployee.h"    
  22. #include "BasePlusCommissionEmployee.h"   
  23.   
  24. int main()  
  25. {  
  26.    // set floating-point output formatting  
  27.    cout << fixed << setprecision( 2 );     
  28.      
  29.    // create vector of four base-class pointers  
  30.    vector < Employee * > employees( 4 );  
  31.   
  32.    // initialize vector with various kinds of Employees  
  33.    employees[ 0 ] = new SalariedEmployee(   
  34.       "John""Smith""111-11-1111", 800 );  
  35.    employees[ 1 ] = new HourlyEmployee(   
  36.       "Karen""Price""222-22-2222", 16.75, 40 );  
  37.    employees[ 2 ] = new CommissionEmployee(   
  38.       "Sue""Jones""333-33-3333", 10000, .06 );  
  39.    employees[ 3 ] = new BasePlusCommissionEmployee(   
  40.       "Bob""Lewis""444-44-4444", 5000, .04, 300 );  
  41.   
  42.    // polymorphically process each element in vector employees  
  43.    for ( size_t i = 0; i < employees.size(); i++ )   
  44.    {  
  45.       employees[ i ]->print(); // output employee information  
  46.       cout << endl;  
  47.   
  48.       // downcast pointer  
  49.       BasePlusCommissionEmployee *derivedPtr =  
  50.          dynamic_cast < BasePlusCommissionEmployee * >   
  51.             ( employees[ i ] );  
  52.   
  53.       // determine whether element points to base-salaried   
  54.       // commission employee  
  55.       if ( derivedPtr != 0 ) // 0 if not a BasePlusCommissionEmployee  
  56.       {  
  57.          double oldBaseSalary = derivedPtr->getBaseSalary();  
  58.          cout << "old base salary: $" << oldBaseSalary << endl;  
  59.          derivedPtr->setBaseSalary( 1.10 * oldBaseSalary );  
  60.          cout << "new base salary with 10% increase is: $"   
  61.             << derivedPtr->getBaseSalary() << endl;  
  62.       } // end if  
  63.         
  64.       cout << "earned $" << employees[ i ]->earnings() << "\n\n";  
  65.    } // end for     
  66.    
  67.    // release objects pointed to by vector抯 elements  
  68.    for ( size_t j = 0; j < employees.size(); j++ )   
  69.    {  
  70.       // output class name  
  71.       cout << "deleting object of "   
  72.          << typeid( *employees[ j ] ).name() << endl;  
  73.   
  74.       delete employees[ j ];  
  75.    } // end for  
  76.   
  77.    return 0;  
  78. // end main  

输出结果:




  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值