C++ 将基类型传递给纯虚函数

C++ passing base type to pure virtual function

我想了解派生 class 中的纯虚函数在向其传递与(抽象)基 class.

相同类型的参数时的行为

为了澄清问题,我从 GeeksForGeeks 获取了以下代码并对其进行了修改:

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 */ }
};

}

现在,我们如何才能访问派生 class Manager 中的字段 degree 以更新他的 degree?因为传递给 raiseSalary(Employee& employee) 的参数可能是 ManagerEngineer

我认为你不能,这是我们想要的行为。

执行此操作的唯一方法是强制转换参数(这在 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 作为 this 参数传递。不幸的是,这在需要多个参数的复杂情况下不起作用。但是,这是语言设计者的想法。完美的语言尚未开发

您对 class 虚函数的概念理解有误。 class "knows" 是什么(通过 vtable),所以你可以把它写成 class 函数,而不是静态全局函数。 class 中的每个函数都知道所有 class 变量,因此您不必传递 class.

的对象
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();   */

我认为有两种方法可以解决这个问题。让我们从一些非常糟糕的解决方案开始:使用转换。那样的话dynamic_cast。您可以尝试向下转换类型。如果 dynamic_cast 无法做到这一点,它将成为 return 一个空指针或抛出异常(取决于你投射指针或 value/reference 类型)。但这种方法将迫使你调整演员阵容,因为将会有更多的经理、工程师类型出现。您可能还需要使用 friend 来允许特定 类 访问其他人的内部信息。 friend 不会在层次结构中被继承,所以你会和很多朋友一起结束 => 坏了,坏了,坏了:(

另一种方法是使用访问者模式:http://en.wikipedia.org/wiki/Visitor_pattern 使用访问者模式,您还可以创建一个基本的无操作访问者和更细粒度的访问者来处理特定的东西。举个小例子(没有推导的特定访问者):

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
    {
      //...
    }
  };

}

在你处理 C++ 的最后,尽量避免使用虚函数 :) 并将所有内容移至静态多态 :)