【问题标题】:Choose derived class at runtime and run unique class method在运行时选择派生类并运行唯一的类方法
【发布时间】:2021-04-14 12:36:40
【问题描述】:

是否可以在运行时选择派生类,然后执行具有不同参数编号/类型的方法?例如,我们有基类Fruit

class Fruit{
    public:
        int weight;
        Fruit(int);
};

Fruit::Fruit(int w) : weight(w){};

带有派生类AppleOrange

class Apple : public Fruit {
    public:
        void eat(int);
        Apple(int);
};

Apple::Apple(int w) : Fruit(w){};

void Apple::eat(int amount){
    weight -= amount;
};
class Orange : public Fruit {
    public:
        void eat(int, bool);
        Orange(int);
};

Orange::Orange(int w) : Fruit(w){};

void Orange::eat(int amount, bool peel){
    if (peel){
         weight /= 10;
    }
    weight -= amount;
};

它们都有eat 方法,但参数不同。如何选择在运行时创建哪个派生类然后执行eat

int main(){
    // read input i.e. (apple, 5) or (orange, 2, true)
    // create either apple or orange 
    // eat it
}

【问题讨论】:

  • 好吧,你可以使用类似命令模式的东西。使用构造函数作为参数,然后在虚函数中执行您的操作。
  • 如果你输入(orange, 5)会发生什么?

标签: c++ oop derived-class variant


【解决方案1】:

多态的目标是不知道你正在访问的对象的具体细节。在这种情况下,由于Orange 有一个额外的peel 操作,而Apple 没有,所以我会采用更像这样的方法:

class Peelable {
public:
    virtual void peel() = 0;
};

class Fruit {
public:
    int weight;

    Fruit(int weight) : weight(weight) {}
    virtual ~Fruit() = default;

    void eat(int amount) { weight -= amount; }
};

class Apple : public Fruit {
public:
    Apple(int weight) : Fruit(weight) {}
};

class Orange : public Fruit, public Peelable {
public:
    Orange(int weight) : Fruit(weight) {}
    void peel() override { weight /= 10; }
};

int main() {
    // read input i.e. (apple, 5) or (orange, 2, true)

    // create either apple or orange 
    Fruit *f = new /* Apple(5), Orange(2), ... */;

    // eat it
    Peelable *p;
    if ((p = dynamic_cast<Peelable*>(f)) && shouldPeel) {
        p->peel();
    }
    f->eat();

    delete f;
}

【讨论】:

    【解决方案2】:

    使用类似于command pattern 的方法。通过构造函数传递不同的参数,并在需要时执行eat方法的不同实现。像这样:

    class Fruit {
      public:
      int weight;
      Fruit(int);
      virtual void eat() = 0;
    };
    
    Fruit::Fruit(int w) : weight(w){};
    
    class Apple : public Fruit {
      public:
      void eat() override;
      Apple(int, int);
      int amount;
    };
    
    Apple::Apple(int w, int a) : Fruit(w){};
    
    void Apple::eat() { weight -= amount; };
    
    class Orange : public Fruit {
      public:
      void eat() override;
      Orange(int, int, bool);
      int amount;
      bool peel;
    };
    
    Orange::Orange(int w, int a, bool p) : Fruit(w), amount{a}, peel{p} {};
    
    void Orange::eat() {
      if (peel) {
        weight /= 10;
      }
      weight -= amount;
    };
    

    【讨论】:

      猜你喜欢
      • 2012-06-23
      • 2010-12-13
      • 1970-01-01
      • 2011-08-05
      • 1970-01-01
      • 2018-06-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多