C++ C++;将基类型传递给纯虚函数
我想了解在向派生类传递与(抽象)基类相同类型的参数时,派生类中纯虚函数的行为 为了澄清这个问题,我从Geeksforgeks那里获取了以下代码并对其进行了修改:C++ C++;将基类型传递给纯虚函数,c++,abstract-class,virtual,C++,Abstract Class,Virtual,我想了解在向派生类传递与(抽象)基类相同类型的参数时,派生类中纯虚函数的行为 为了澄清这个问题,我从Geeksforgeks那里获取了以下代码并对其进行了修改: namespace example { enum Type {ENGINEER, MANAGER}; class Employee { private: const Type worker; public: Employee(const Type& worker) : worker(worker) {}
namespace example {
enum Type {ENGINEER, MANAGER};
class Employee
{
private:
const Type worker;
public:
Employee(const Type& worker) : worker(worker) {}
virtual ~Employee {}
virtual void raiseSalary(const Employee&) = 0;
{ /* common raise salary code */ }
virtual void promote(const Employee&) = 0;
{ /* common promote code */ }
};
class Manager: public Employee {
private:
int degree;
public:
//<constructor>\\
virtual void raiseSalary(const Employee&)
{ /* Manager specific raise salary code, may contain
increment of manager specific incentives*/ }
virtual void promote(const Employee&)
{ /* Manager specific promote */ }
};
名称空间示例{
枚举类型{ENGINEER,MANAGER};
班级员工
{
私人:
固定式工人;
公众:
雇员(常数类型和工作者):工作者(工作者){}
虚拟~Employee{}
虚空增加额(警察雇员&)=0;
{/*通用加薪代码*/}
虚拟作废升级(const-Employee&)=0;
{/*通用升级代码*/}
};
班级经理:公职人员{
私人:
智力度;
公众:
//\\
虚拟无效提高工资(警察雇员&)
{/*特定于经理的加薪代码,可能包含
经理特定奖励的增量*/}
虚拟作废升级(const-Employee&)
{/*特定于管理器的升级*/}
};
}
现在,我们如何访问派生类
管理器中的字段degree
,以便更新他的degree
?由于传递给的参数raiseSalary(Employee&Employee)
可能是经理
或工程师
,我认为您不能,这是您想要的行为
唯一的方法是把你的论点(C++中的四个不同类型的转换)复杂化。另一个解决方案是给任何员工一个等级属性
亚历克西斯 您应该这样构造代码:
class Employee
{
virtual void raiseSalary() = 0;
virtual void promote() = 0;
};
class Manager: public Employee
{
virtual void raiseSalary()
{ /* Manager specific raise salary code, may contain... */ }
virtual void promote()
{ /* Manager specific promote */ }
};
int main()
{
Manager bob;
bob.promote(); // <--- Proper method in the Manager class will be called.
// Current instance will always have the right class.
}
class员工
{
虚空raiseSalary()=0;
虚空提升()=0;
};
班级经理:公职人员
{
虚空上升幅度()
{/*经理特定的加薪代码,可能包含…*/}
虚拟空间升级()
{/*特定于管理器的升级*/}
};
int main()
{
经理鲍勃;
bob.promote();//您错误地理解了虚拟函数与类的概念。类“知道”它是什么(通过vtable),因此您可以将其作为类函数而不是静态全局函数编写。类中的每个函数都知道所有类变量,因此您不必传递类的对象
namespace example {
enum Type {ENGINEER, MANAGER};
class Employee
{
private:
const Type worker;
public:
Employee(const Type& worker) : worker(worker) {}
virtual ~Employee {}
virtual void raiseSalary() = 0;
{ /* common raise salary code */ }
virtual void promote() = 0;
{ /* common promote code */ }
};
class Manager: public Employee {
private:
int degree;
public:
//<constructor>\\
virtual void raiseSalary()
{
//the Employed standard code
Employee::raiseSalary(); //This won't compile since you set the virtual function = 0
//Manager specific raise salary code
degree = 0; //this lazy bastards should do real work like coding stuff
}
virtual void promote()
{
Employee::promote(); //employee common code. This won't compile since you set the virtual function = 0
/* Manager specific promote */
degree = degree * 2;
}
};
Employee array[10];
array[0] = Manager(); //create a manager object on the stack
array[1] = Manager(); //create a manager object on the stack
array[0].raiseSalary(); //Only Mananer0 gets raiseSalary
/*the manager object in array[0] uses its virtual function
to the manager raiseSalary function. The Manager RaiseSalary function
in this case calls the base class raiseSalary function explicitly
via Employee::raiseSalary(); */
名称空间示例{
枚举类型{ENGINEER,MANAGER};
班级员工
{
私人:
固定式工人;
公众:
雇员(常数类型和工作者):工作者(工作者){}
虚拟~Employee{}
虚空raiseSalary()=0;
{/*通用加薪代码*/}
虚空提升()=0;
{/*通用升级代码*/}
};
班级经理:公职人员{
私人:
智力度;
公众:
//\\
虚空上升幅度()
{
//使用的标准代码
Employee::raiseSalary();//由于将虚拟函数设置为0,因此无法编译此函数
//经理特定加薪代码
degree=0;//这个懒惰的混蛋应该像编码一样做真正的工作
}
虚拟空间升级()
{
Employee::promote();//员工公用代码。由于将虚拟函数设置为0,因此无法编译此代码
/*特定于经理的晋升*/
度=度*2;
}
};
Employee数组[10];
数组[0]=Manager();//在堆栈上创建管理器对象
数组[1]=管理器();//在堆栈上创建管理器对象
数组[0]。RaiseSaly();//只有Mananer0才能获取RaiseSaly
/*数组[0]中的管理器对象使用其虚拟函数
到manager RaiseSaly函数。manager RaiseSaly函数
在这种情况下,显式调用基类raiseSalary函数
通过Employee::raiseSalary()*/
我认为有两种方法可以解决这个问题。让我们从一些非常糟糕的解决方案开始:使用强制转换。在这种情况下,动态强制转换
。您可以尝试向下强制转换类型。如果动态强制转换
不能这样做,它将返回空指针或引发异常(取决于是强制转换指针还是值/引用类型)。但这种方法将迫使您调整您的类型转换,因为将出现更多的经理、工程师类型。您可能还需要使用friend
来允许特定类访问其他类的内部。friend
不会在层次结构中继承,因此您将有许多朋友=>破碎、破碎,b罗肯:(
另一种选择是使用访问者模式:
使用访问者模式,您还可以创建基本的无操作访问者和更细粒度的访问者来处理特定的内容。仅举一个小例子(对于没有派生的特定访问者):
名称空间示例{
阶级加薪访客;
班级员工促进访客;
班级员工
{
公众:
雇员(){}
//不要忘记实现复制构造函数:阅读更多关于规则3的内容!!!
虚拟~Employee{}
虚拟无效接受(SalaryRaisingVisitor常量&)=0;
虚拟无效接受(EmployeePromotingVisitor常量&)=0;
};
班级经理:公职人员{
私人:
智力度;
公众:
//
虚拟无效接受(加薪访客const&v)
{
v、 访问(*本,学位);
}
虚拟无效接受(员工推动访客const&v)
{
v、 访问(*本,学位);
}
};
班主任:公职人员{
公众:
//
虚拟无效接受(加薪访客const&v)
{
v、 访问(*本);
}
虚拟无效接受(员工推动访客const&v)
{
v、 访问(*本);
}
};
阶级加薪访客
{
void visit(Manager&m、int°ree)//如果没有内部状态更改,则可能是常量
{
//...
}
无效访问(工程师和工程师)//如果没有内部状态更改,则可能为常量
{
//...
}
};
}
最后,在处理C++时,尽量避免虚拟函数:将所有的东西移到静态多态性:
使用<代码> STATICE-CAST
namespace example {
class SalaryRaisingVisitor;
class EmployeePromotingVisitor;
class Employee
{
public:
Employee() {}
//don't forget to implement the copy constructor: read more about rule of 3!!!
virtual ~Employee {}
virtual void accept(SalaryRaisingVisitor const&) = 0;
virtual void accept(EmployeePromotingVisitor const&) = 0;
};
class Manager: public Employee {
private:
int degree;
public:
//<constructorS>
virtual void accept(SalaryRaisingVisitor const& v)
{
v.visit(*this, degree);
}
virtual void accept(EmployeePromotingVisitor const& v)
{
v.visit(*this, degree);
}
};
class Engineer: public Employee {
public:
//<constructorS>
virtual void accept(SalaryRaisingVisitor const& v)
{
v.visit(*this);
}
virtual void accept(EmployeePromotingVisitor const& v)
{
v.visit(*this);
}
};
class SalaryRaisingVisitor
{
void visit(Manager& m, int& degree) //might be const if no internal state changes
{
//...
}
void visit(Engineer& e) //might be const if no internal state changes
{
//...
}
};
}