双重调度通常通过访问者模式使用,但在您的情况下,这有点奇怪,因为访问者本身就是元素......坚持住!
简而言之,这个想法:
- 从一对
IShape
/开始IShape
,命名left
并right
从现在开始
- 在作为参数传递时调用该
intersect
方法,在该方法中知道它的确切类型(它是一个!)并通过调用on的正确重载来通知它(接受 a 的那个)left
right
intersect
left
Sphere
right
intersect
right
Sphere
- 在
intersect
调用中right
,right
知道它的确切类型,嘿,我们也传递了确切的类型left
,所以现在我们都知道了!
一个简单的实现:
class IShape {
public:
virtual ~IShape() {}
virtual bool intersect(IShape const& other) const = 0;
virtual bool intersect(Box const& other) const = 0;
virtual bool intersect(Sphere const& other) const = 0;
}; // class IShape
class Box: public IShape {
public:
virtual bool intersect(IShape const& other) const override {
std::cout << "-> Box::intersect(IShape)\n";
return other.intersect(*this);
}
virtual bool intersect(Box const& other) const override {
std::cout << "-> Box::intersect(Box)\n";
/* compute intersection of two boxes */
return false;
}
virtual bool intersect(Sphere const& other) const override {
std::cout << "-> Box::intersect(Sphere)\n";
/* compute intersection of a box and a sphere */
return false;
}
}; // class Box
// Likewise implementation of Sphere
一个完整的实现给出了这个输出:
int main() {
Box const box;
Sphere const sphere;
IShape const& ibox = box;
IShape const& isphere = sphere;
box.intersect(sphere);
// output
// -> Box::intersect(Sphere)
ibox.intersect(sphere);
// output
// -> Box::intersect(Sphere)
sphere.intersect(ibox);
// output
// -> Sphere::intersect(IShape)
// -> Box::intersect(Sphere)
isphere.intersect(ibox);
// output
// -> Sphere::intersect(IShape)
// -> Box::intersect(Sphere)
}
这种策略被命名为双重分派,因为从 IShape/IShape 开始时有两个连续的双重分派,每个变量一个分派,需要为其“推导”动态类型。