这是更好的方法来检查对象类型 [英] which is the better approach to check object type
问题描述
方法:1
class Employee
{
public:
virtual int calculateSalary ()= 0;
};
类PermanentEmployee:public Employee {
const int salaryPerMonth;
public:
PermanentEmployee(int sal):salaryPerMonth(sal){}
int calculateSalary(){
return salaryPerMonth;
}
};
class ContractEmployee:public Employee {
const int wagesPerHr;
int totalHour;
public:
ContractEmployee(int sal):wagesPerHr(sal),totalHour(0){}
void setWorkingDuration(int time){
totalHour = totalHour +时间;
}
int calculateSalary(){
return wagesPerHr * totalHour;
}
};
类经理{
list< Employee *> ls;
public:
void assignWorkingHour(){
list< Employee *> :: iterator it;
for(it = ls.begin(); it!= ls.end(); it ++){
Employee * emp = * it;
ContractEmployee * contractEmp = dynamic_cast< ContractEmployee *>(emp);
if(contractEmp){
contractEmp-> setWorkingDuration(5);
}
}
}
};
在问题中,有两种类型的Employee:PermanentEmployee和ContractEmployee。
有一个名为Manager的类,其中包含在他下工作的所有员工的列表。
对于ContractEmployee,它必须调用setWorkingDuration函数,该函数在类Manager中的方法assignWorkingHour中调用。
问题是:
of Employee由dynamic_cast运算符确定,并且Manager必须知道Employee的所有类型的派生类
approach2:在Employee类中添加另一个成员
枚举TypeOfEmployee {CONTRACT,PERMANENT};
并检查TypeOfEmployee以确定Employee类型
更好的方法是编写代码, t需要有关确切对象类型的知识。对我来说,最优雅的方式是将 setWorkingDuration()
移动到employee类。可能这样:
class Employee
{
public:
//计算工资为这个雇员。
//返回计算的薪水。
virtual int calculateSalary()= 0;
//设置工作持续时间。如果员工是永久的,什么也不做。
//如果Employee在合同上则返回true,如果为永久则返回false。
virtual bool setWorkingDuration(int time)
{
return false;
}
};
类PermanentEmployee:public Employee
{
const int salaryPerMonth;
public:
PermanentEmployee(int sal):salaryPerMonth(sal){}
int calculateSalary()
{
return salaryPerMonth;
}
};
class ContractEmployee:public Employee
{
const int wagesPerHr;
int totalHour;
public:
ContractEmployee(int sal):wagesPerHr(sal),totalHour(0){}
int calculateSalary()
{
return wagesPerHr * totalHour;
}
bool setWorkingDuration(int time)
{
totalHour = totalHour + time;
return true;
}
};
class Manager
{
list< Employee *> ls;
public:
void assignWorkingHours()
{
list< Employee *> :: iterator it;
for(it = ls.begin(); it!= ls.end(); it ++)
{
Employee * emp = * it;
emp-> setWorkingDuration(5);
}
}
};
不得不知道
Employee
实际上是PermanentEmployee
还是ContractEmployee
。这就是多态性给你。一般来说,如果你必须使用dynamic_cast<>
,你可能想再看看设计,看看你是否可以省略它。Approach :1
class Employee { public: virtual int calculateSalary() = 0; }; class PermanentEmployee : public Employee { const int salaryPerMonth; public: PermanentEmployee(int sal) : salaryPerMonth(sal){} int calculateSalary() { return salaryPerMonth; } }; class ContractEmployee : public Employee { const int wagesPerHr; int totalHour; public: ContractEmployee(int sal) : wagesPerHr(sal), totalHour(0){} void setWorkingDuration(int time) { totalHour = totalHour + time; } int calculateSalary() { return wagesPerHr * totalHour; } }; class Manager { list<Employee *> ls; public: void assignWorkingHour() { list<Employee *>::iterator it; for(it = ls.begin(); it != ls.end(); it++) { Employee *emp = *it; ContractEmployee* contractEmp = dynamic_cast<ContractEmployee* >(emp); if(contractEmp) { contractEmp->setWorkingDuration(5); } } } };
In problem, there are 2 type of Employee : PermanentEmployee and ContractEmployee. There is a class called Manager which contains a list of all employee working under him. For ContractEmployee, it has to invoke function setWorkingDuration, which is being invoked in method assignWorkingHour of class Manager.
The problem is: Here type of Employee is being determind by dynamic_cast operator and Manager has to know about all type of derive class of Employee
approach2: add another member in class Employee
enum TypeOfEmployee {CONTRACT, PERMANENT};
and check TypeOfEmployee to determine the type of Employee
Please tell which is better or Is there any alternative approach?
解决方案The better approach is to write code that doesn't require knowledge about the exact object type. Seems to me the most elegant way to deal with this is to move the
setWorkingDuration()
to the employee class. Probably like this:class Employee { public: // Calculates the salary for this employee. // Returns the calculated salary. virtual int calculateSalary() = 0; // Sets the working duration. Does nothing if the employee is permanent. // Returns true if Employee is on a contract, false if permanent. virtual bool setWorkingDuration(int time) { return false; } }; class PermanentEmployee : public Employee { const int salaryPerMonth; public: PermanentEmployee(int sal) : salaryPerMonth(sal) {} int calculateSalary() { return salaryPerMonth; } }; class ContractEmployee : public Employee { const int wagesPerHr; int totalHour; public: ContractEmployee(int sal) : wagesPerHr(sal), totalHour(0) {} int calculateSalary() { return wagesPerHr * totalHour; } bool setWorkingDuration(int time) { totalHour = totalHour + time; return true; } }; class Manager { list<Employee *> ls; public: void assignWorkingHours() { list<Employee *>::iterator it; for(it = ls.begin(); it != ls.end(); it++) { Employee* emp = *it; emp->setWorkingDuration(5); } } };
This way, the
Manager
class doesn't have to know whether theEmployee
is actually aPermanentEmployee
or aContractEmployee
. That is what polymorphism gives you. Generally speaking if you have to usedynamic_cast<>
, you may want to take another look at the design and see if you can omit it.这篇关于这是更好的方法来检查对象类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!