问题描述
是否可以在运行时选择派生类,然后执行具有不同参数编号/类型的方法?例如,我们有基类 Fruit
class Fruit{
public:
int weight;
Fruit(int);
};
Fruit::Fruit(int w) : weight(w){};
带有派生类 Apple
和 Orange
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
}
解决方法
使用类似于 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;
};
,
多态的目标是不知道您正在访问的对象的具体细节。在这种情况下,由于 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;
}