我必须就泛化与多态性做出决定。
这个场景是标准的:我想让我的整体相互依赖 代码更加模块化,清洁和可扩展。 它仍然处于可以改变设计原则的阶段, 而且,正如我所看到的,非常可取。
我会介绍纯虚基类(接口)或模板吗?
我了解有关模板选项的基础知识: 减少间接,更好的性能,更多的编译 但 没有后期绑定,等等。
stl不使用太多(或没有?)继承,而boost也没有。 但我认为这些都是非常小的基本工具 程序员编写2行代码。
我认为继承和后期绑定方法更为明智 插件样式的大块代码和功能应该可以互换, 部署后甚至在运行时期间可更新等。
我的情景有点介于两者之间。
我不需要在运行时动态交换代码片段,编译时间很好。 通常它也是一个非常核心且经常使用的功能, 它在逻辑上不能分成大块。
这让我倾向于模板解决方案。 对我来说,它看起来也更清洁了。
是否有任何重大不良影响,界面仍然是这样的 去?他们什么时候不是? 哪个更符合标准的c ++风格?
我知道这接近于主观,但我真的很感兴趣 一些经验。我没有Scott Meyers有效C ++的副本 所以我寄希望于你们:)
答案 0 :(得分:24)
你基本上是正确的,当允许在运行时更改类型时(例如在插件架构中),动态多态(继承,虚拟)通常是正确的选择。如果类型只应在编译时更改,则静态多态(模板)是更好的选择。
模板的唯一潜在缺点是1)它们通常必须在头文件中定义(这意味着更多的代码被#included),这通常会导致编译时间变慢。
但从设计角度来看,我无法在可能的情况下使用模板时遇到任何问题。
符合标准c ++的更多内容 风格?
取决于“标准C ++风格”。 C ++标准库使用了一切。 STL使用模板来处理所有事情,稍微旧的IOStreams库使用继承和虚函数,当然,从C继承的库函数也不使用。
现在,模板是迄今为止最受欢迎的选择,我不得不说这是最“标准”的方法。
答案 1 :(得分:10)
经典面向对象多态的属性:
dynamic_cast
的需要(以及它可能会炸成客户的脸)可能很容易弥补这一点模板编译时多态的属性:
请注意,无需任何一个决定。你可以自由地混合和混合它们(以及许多其他习语和范例)。通常,这会导致非常令人印象深刻(和富有表现力)的代码。 (例如,请参阅类型擦除等内容。)为了通过巧妙地混合范例来了解可能的内容,您可能希望浏览Alexandrescu的“现代C ++设计”。
答案 2 :(得分:8)
这是一种虚假的反对意见。是的,继承和虚函数的主要用途是iostreams
,它们非常陈旧,并且以与std
库的其余部分完全不同的风格编写。
但许多“最酷”的现代C ++库(如boost)确实利用了运行时多态性,他们只是使用模板来使它更方便使用。
boost::any
和std::tr1::function
(以前也来自提升)就是很好的例子。
它们都是单项容器,其具体类型在编译时是未知的(对any
来说尤其明显,因为它有自己的动态转换运算符来获取值)。 / p>
答案 3 :(得分:4)
在我的盘子上有更多经验之后,模板中有一些我不喜欢的东西: 将模板元编程视为可用语言是不合格的:
所有这些,我在基本实用程序和库上使用它非常成功。用它编写高级功能或硬件相关的东西,似乎并不适合我。 意思是我模板化我的构建块,但用经典的方式构建房子。
答案 4 :(得分:0)
从我的角度来看,这是你最擅长的。如果您有更多OO使用OO的经验。如果您有更多使用仿制药的经验。
这两种技术都有一些等效的模式,这些模式对很多你可以使用的东西都意味着。 OO中的EG策略与泛型中的策略或OO中的模板方法与泛型中的通常重复模板模式。
如果您计划的重构生产代码已经有效,但结构有点臭。不要以它为借口来使用一些新的设计技术,因为在一两年内,一旦你更好地理解了这种技术,你可能会后悔如何重构你的代码。在学习它们时应用技术时,很容易引入新的不灵活性。如果您不熟练掌握如何知道自己正在改进设计而不是在代码中构建大型阴茎符号,那么目的是改进现有代码的设计。
就我个人而言,我更擅长OO并倾向于支持它,因为我知道我可以制作易于理解的清洁设计,并且大多数人都可以改变。我正确的大多数通用代码旨在与其他通用代码接口,例如编写迭代器或算法的通用函数。
答案 5 :(得分:0)
我在我的大型代码库中使用它们。当在编译时知道类型时,我用模板设计它,当它只在运行时知道时,我使用虚函数。我发现虚拟函数更容易编程,以后更容易阅读,但有时候性能是关键的,并且模板化的多态(如果你真的可以称之为多态)可以内联真的有帮助。