[我接受了一家金融公司的采访,并被问到以下问题:“比起模板,您更喜欢虚拟功能时列出案例?”
这听起来很奇怪,因为通常我们的目标是相反的权利?所有的书籍,文章和讲座都鼓励我们使用静态多态性而不是动态多态性。
我是否不知道何时应该使用虚函数并避免使用模板?
如果在编译时不知道对象的类型,请使用virtual
方法。
例如
void Accept (Fruit* pFruit) // supplied from external factors at runtime
{
pFruit->eat(); // `Fruit` can be anyone among `Apple/Blackberry/Chickoo/`...
}
根据用户输入的内容,将向该功能提供水果。因此,我们没有办法弄清楚是什么eat()
。因此,它是运行时多态性的候选者:
class Fruit
{
public: virtual void eat () = 0;
}
在所有其他情况下,总是更喜欢静态多态性(包括template
s)。它更具确定性且易于维护。
GUI /可视化窗口小部件工具箱是一个明显的例子。例如,重新实现draw
方法对于虚拟方法和动态分派来说无疑省事了。而且由于现代C ++倾向于不鼓励原始指针管理,因此std::unique_ptr
可以为您管理资源。
[我确定您还有很多其他层次示例,可以为您提供...一个游戏的基础std::unique_ptr
类,其中包含处理各种不良行为的虚拟方法:)
今天,动态调度的整个“开销”论点完全没有价值。我认为,数十年来,vtable间接实现对于严重的工作负载而言并不是很大的开销。还有一个更有趣的问题,如果今天设计C ++,多态性将成为语言的一部分吗?但这既不是现在也不是那里。
我不希望这个问题仍然存在,因为这不是直接的编程问题,而且很可能会引起人们的意见。对于enemy
,可能是一个更好的问题。
面试问题似乎在询问您的偏好(和您的抚慰)。我更喜欢接口(虚拟方法),以便于为单元测试创建模拟。我们可以为它们使用模板,但是它很麻烦(必须将消费者作为模板)。如果使用vtable查找进行性能分析不会导致速度下降,则应优先于模拟/测试非虚拟方法。
此外,键入擦除。我认为完全不能使用模板来实现。类型擦除可以粗略地认为是void ptr和函数指针,可以使用接口+虚拟方法轻松实现。
模板需要提供代码实现。我相信可以仅使用其二进制(对象)文件在子ptr上调用接口的虚拟方法。
不确定使用模板的代码膨胀是否是现代编译器的问题,但是如果可执行文件的大小显着增加,在内存有限的嵌入式系统中这可能是个问题,并且它们不希望使用模板。