现在假设公司为员工发放工资,不同员工的工资计算方法并不相同:A类和B类员工有基本工资加绩效。C类员工只是基本工资。class AEmployee{public: //计算基本工资 doublegetSalary(); //计算绩效 doublegetPerformance();};class BEmployee{public: //计算基本工资 doublegetSalary(); //计算绩效 doublegetPerformance();};class CEmployee{public: //计算基本工资 doublegetSalary();};
需要做一个工资发放类,可以调用每个员工类的工资计算方法,并发放工资。为了让工资发放类可以根据员工类型不同,使用对应的工资计算函数,将其设计为一个模板类,针对C类员工进行全特化:template<typename Employee>class DistributeWages{public: //发放基本工资 voidDistributeSalary(); //发放绩效 voidDistributePerformance();};//全特化针对C类员工//没有绩效发放template<>class DistributeWages<CEmployee>{public: //发放基本工资 voidDistributeSalary();};
突然有一天,公司良心发现,决定对绩效加发20%的奖金。为此,你决定派生DistributeWages类,完成此效果:template<typename Employee>class NewDistributeWages : public DistributeWages<Employee>{public: //发放基本工资 voidDistributeSalary(); //发放绩效加奖金 voidDistributeAndMorePerformance(){ DistributePerformance(); //报错 //计算奖金并发放 ... }};
调用基类的绩效发放函数DistributePerformance时,会报错。这是由于编译器并不知道你到底继承了一个什么样的DistributeWages类。如果是针对C类员工的全特化类,根本没有DistributePerformance函数。如果你明确知道自己只用于A类和B类员工,应该怎样去实现呢?//使用this->template<typename Employee>class NewDistributeWages : public DistributeWages<Employee>{public: //发放基本工资 voidDistributeSalary(); //发放绩效加奖金 voidDistributeAndMorePerformance(){ this->DistributePerformance(); //计算奖金并发放 ... }};//使用using template<typename Employee>class NewDistributeWages : public DistributeWages<Employee>{public: //使用using using DistributeWages<Employee>::DistributePerformance; //发放基本工资 voidDistributeSalary(); //发放绩效加奖金 voidDistributeAndMorePerformance(){ DistributePerformance(); //计算奖金并发放 ... }};//明确指出函数位置template<typename Employee>class NewDistributeWages : public DistributeWages<Employee>{public: //发放基本工资 voidDistributeSalary(); //发放绩效加奖金 voidDistributeAndMorePerformance(){ DistributeWages<Employee>::DistributePerformance(); //计算奖金并发放 ... }};
以上三种方法都向编译器承诺DistributePerformance函数一定在基类中,让其通过编译。不过明确资格修饰有一个弊端是,如果DistributePerformance是虚函数,其动态绑定便失效了。