标题根本不是很有描述性,但我把你放在了情境中(我正在学习多态性)。
假设我们有两个类:
基类:CommissionEmployee
派生类:EmployeeBasePlusCommission
我将从这些类中创建两个对象,并为每个对象创建两个指针:
EmpleadoPorComision empleadoPorComision("Sue", "Jones", "222-222-2221", 1000, 0.06);
EmpleadoPorComision *empleadoPorComisionPtr = 0;
EmpleadoBaseMasComision empleadoBaseMasComision("Bob", "Lewis", "333-332-1122", 5000, 0.04, 300);
EmpleadoBaseMasComision *empleadoBaseMasComisionPtr = 0;
现在我们将调用“打印”方法。该方法属于基类,只是在派生类中,它也有这个“打印”方法,并且在其中调用了基类的打印+显示派生类属性的函数。
现在我要做的是使用这些指针使用 print 方法:
empleadoPorComisionPtr = &empleadoPorComision;
empleadoPorComisionPtr->imprimir(); //Invoca a imprimir de la clase base
empleadoBaseMasComisionPtr = &empleadoBaseMasComision;
empleadoBaseMasComisionPtr->imprimir(); //Invoca a imprimir de la clase derivada
到目前为止一切顺利,问题是当我这样做时:
empleadoPorComisionPtr = &empleadoBaseMasComision;
empleadoPorComisionPtr->imprimir(); //Invoca a la funcion imprimir de la clase base
最后一个 print() 调用 print 但来自基类。可以看到,其实我是在告诉最后一个指针(employeePorCommissionPtr)指向employeeBasePlusCommission对象,也就是指向派生类的一个对象,但是,为什么它使用的print方法是基类的呢?类,而不是派生类中的那个?
非常感谢大家,问候。
编辑:
类的定义:
CommissionEmployee 基类定义:
class EmpleadoPorComision
{
public:
EmpleadoPorComision(const string &, const string &, const string &, double=0.0, double=0.0);
void establecerPrimerNombre(const string&); //Establece el primer nombre
string conseguirPrimerNombre() const; //Devuelve el primer conseguirPrimerNombre
void establecerApellidoPaterno(const string&);
string conseguirApellidoPaterno() const;
void establecerNumeroSS(const string&);
string conseguirNumeroSS() const;
void establecerVentasBrutas(double);
double conseguirVentasBrutas() const;
void establecerTarifaComision(double);
double conseguirTarifaComision() const;
double ingresos() const; //Calcula los ingresos
void imprimir() const; //Imprime el objeto EmpleadoPorComision
private:
string primerNombre;
string apellidoPaterno;
string numeroSS;
double ventasBrutas; //Ventas brutas por semana
double tarifaComision; //Porcentaje de comision
};
定义派生类 EmployeeBasePlusCommission:
class EmpleadoBaseMasComision : public EmpleadoPorComision
{
public:
EmpleadoBaseMasComision(const string&, const string&, const string&, double=0.0, double=0.0, double=0.0);
void establecerSalarioBase(double);
double conseguirSalarioBase() const;
double ingresos() const;
void imprimir() const;
private:
//El resto de miembros de datos se heredan de la clase base.
double salarioBase;
};
为了使多态在这种情况下起作用,即调用子类的函数,有必要将要覆盖的函数在基类中标记为虚拟:
此外,从 C++11 开始,建议将覆盖虚拟函数的派生类的函数标记为
override
:这样,如果函数不会被覆盖(因为你基本上搞砸了),编译器将显示一条错误消息:
为什么没有虚拟多态就不能工作?
当调用一个普通的(不是虚拟的,要清楚)成员函数时,编译器会生成一个直接的函数调用,即在以下示例中:
由于指针是 type
base
的,编译器将生成对Base::func
even if的调用Derivada::func
。为什么?
基本上,因为非虚拟调用是在编译时计算的,并且由于在编译时编译器只有 type 的指针
Base
,所以要执行的函数将是Base::func
.这是因为 C++ 的意图一直是优化它的速度,所以所有可能的优化都应用于生成的代码。
如果函数是虚拟的呢?
如果将基类的函数声明为
virtual
在编译过程中,会在基类中生成一个函数指针。这个函数指针会指向合适的版本,这样我们就可以从父类调用子类的函数:我所说的函数指针是不可见的。但是,它的效果可以看出,对虚函数的调用明显变慢(而不是直接调用,而是调用函数指针)。