C++ C+中的多分派+;
我试图理解什么是多重分派。我读了很多不同的文本,但我仍然不知道什么是多重分派,它有什么好处。也许我缺少的是一段使用多重分派的代码。请你能用C++多个分派代码在C++中编写一段代码,这样我就可以看到它不能被编译/运行,因为C++只有一个调度。我需要看到区别。谢谢。多重分派是根据传递给函数调用的参数的运行时类型选择要调用的函数版本的功能C++ C+中的多分派+;,c++,multiple-dispatch,C++,Multiple Dispatch,我试图理解什么是多重分派。我读了很多不同的文本,但我仍然不知道什么是多重分派,它有什么好处。也许我缺少的是一段使用多重分派的代码。请你能用C++多个分派代码在C++中编写一段代码,这样我就可以看到它不能被编译/运行,因为C++只有一个调度。我需要看到区别。谢谢。多重分派是根据传递给函数调用的参数的运行时类型选择要调用的函数版本的功能 这里有一个在C++中没有正确工作的例子(未测试): 多重分派是指执行的函数取决于多个对象的运行时类型 C++具有单一分派,因为当您使用虚拟函数时,实际运行的函数只取
这里有一个在C++中没有正确工作的例子(未测试):
多重分派是指执行的函数取决于多个对象的运行时类型 C++具有单一分派,因为当您使用虚拟函数时,实际运行的函数只取决于->或左边对象的运行时类型。接线员 我正在努力思考一个真正的多分派编程案例。也许是在一个不同角色互相争斗的游戏中
void Fight(Opponent& opponent1, Opponent& opponent2);
战斗的胜利者可能取决于两个对手的特征,因此您可能希望根据两个参数的运行时类型将此调用分派给以下其中一个参数:
void Fight(Elephant& elephant, Mouse& mouse)
{
mouse.Scare(elephant);
}
void Fight(Ninja& ninja, Mouse& mouse)
{
ninja.KarateChop(mouse);
}
void Fight(Cat& cat, Mouse& mouse)
{
cat.Catch(mouse);
}
void Fight(Ninja& ninja, Elephant& elephant)
{
elephant.Trample(ninja);
}
// Etc.
函数的作用取决于两个参数的类型,而不仅仅是一个参数。在C++中,你可能需要把它写为一些虚拟函数。将根据一个参数(此指针的参数)选择一个虚拟函数。然后,虚拟函数可能需要包含一个开关或执行其他参数特定的操作。在单次分派中,执行的函数仅取决于对象类型。在里面
双重分派执行的函数取决于对象类型和
参数
在下面的示例中,使用调用函数Area()
单分派和Intersect()
依赖于双分派,因为它需要
形状参数
class Circle;
class Rectangle;
class Shape
{
virtual double Area() = 0; // Single dispatch
// ...
virtual double Intersect(const Shape& s) = 0; // double dispatch, take a Shape argument
virtual double Intersect(const Circle& s) = 0;
virtual double Intersect(const Rectangle& s) = 0;
};
struct Circle : public Shape
{
virtual double Area() { return /* pi*r*r */; }
virtual double Intersect(const Shape& s);
{ return s.Intersect(*this) ; }
virtual double Intersect(const Circle& s);
{ /*circle-circle*/ }
virtual double Intersect(const Rectangle& s);
{ /*circle-rectangle*/ }
};
这个例子就是基于此。C++不直接支持它,但我相信您可以以某种方式模拟它。我从来没有使用过MD,甚至看到了其他语言的好设计,这让我想在C++中拥有MD。迪伦的粉丝们把它列为迪伦的语言特色之一。但据我所知,它闻起来像是一个糟糕的设计,因为你可能需要编写的函数数量呈指数级增长。我不想写那么多函数。只要你使用了
Visitor
模式,你就可以随时使用MD。一个使用C++11的简单示例:谢谢,这个答案正是我需要看到的。现在我只想知道,为什么有人需要这样的东西。。无论如何,谢谢你给我举个好例子。一个应用是物理,一个立方体与另一个立方体碰撞是一个交点,一个立方体与一个平面碰撞是另一个交点。因此,您最终会得到许多不同的碰撞检测方法,而调度在这方面非常有用。这里有一个双分派线程,另一个应用程序使用编程语言。假设希望加号运算符(“+”)在两个参数都是整数时计算整数结果,在任一参数都是浮点时计算浮点,在两个参数都是字符串时计算串联字符串。您有一个从“expression”派生的类型层次结构,因此您希望在说add(exp1,exp2)或expr1->add(expr2)时调用该函数取决于exp1和exp2的实际类型。这里有相当多的空格。@strager 2额外空格:)如果堆栈溢出可以将其格式化为查看器喜欢的空格数,那就太好了。一个实际的、经常发生的例子是,将不同的子类与基类指针数组区别对待。
class Circle;
class Rectangle;
class Shape
{
virtual double Area() = 0; // Single dispatch
// ...
virtual double Intersect(const Shape& s) = 0; // double dispatch, take a Shape argument
virtual double Intersect(const Circle& s) = 0;
virtual double Intersect(const Rectangle& s) = 0;
};
struct Circle : public Shape
{
virtual double Area() { return /* pi*r*r */; }
virtual double Intersect(const Shape& s);
{ return s.Intersect(*this) ; }
virtual double Intersect(const Circle& s);
{ /*circle-circle*/ }
virtual double Intersect(const Rectangle& s);
{ /*circle-rectangle*/ }
};