在面向对象编程中,继承有哪些负面的运行时影响?
我知道继承有一些积极的方面,但我不知道继承的负面运行时影响?谁能告诉我这件事吗,谢谢!
I know there is some positive aspects of inheritance, but I don't know negative runtime impacts of inheritance? Can anybody tell me about that, thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
如果基类包含虚函数,那么它的实例及其后代将各自拥有一个指向虚函数表的指针,从而将其内存占用增加一个指针的大小。与非虚函数相比,对虚函数的调用将具有额外的间接级别,因此调用时间成本很小。
否则不会有任何负面影响。从一个类派生另一个类但不使用多态性(因此,没有虚函数,始终通过指向派生类的指针调用方法)与没有父类的类相比没有任何成本。
更新:我已经在这里解决了继承对性能的影响。其他答案对面向对象的正确性有更多的阐述。
If a base class contains virtual functions then instances of it and its descendants will each have a pointer to a virtual function table, increasing their memory footprint by the size of one pointer. Calls to virtual functions will have an extra level of indirection compared to non-virtual functions, so there is a small call time cost there.
Otherwise, there is no negative impact. Deriving one class from another but not using polymorphism (so, no virtual functions, always calling methods through pointers to the derived class) has no cost over a class with no parent.
Update: I have addressed the performance impact of inheritance here. Other answers have more to say on OO-correctness.
使用继承的好处远远超过了缺点。
第一个缺点是内存中的对象大小,当使用虚函数时,它有一个额外的指向虚函数表的指针。
与常规调用相比,虚拟函数调用还需要在汇编中执行一些额外的步骤。
非虚拟函数调用在性能方面的成本相同。
如果
A
派生自B
,并且包含来自B
的所有信息,则对象大小也会随着A
类的对象而增加代码>.当然,如果经过深思熟虑的设计,这种情况就不会发生,因为即使没有继承,A
也会包含B
中的所有信息。还有一个问题是使用
dynamic_cast
或static_cast
,在无继承的环境中您不会遇到这种情况,但即使使用继承也可以避免这些问题。The benefits of using inheritance greatly outweigh the downfalls.
The first downfall is the object size in memory, which, when using virtual functions, has an extra pointer to the virtual function table.
Virtual function calls also require a few extra steps in the assembly compared to regular calls.
Non-virtual function calls cost the same in terms of performance.
Object size can also increase as an object of class
A
, ifA
is derived fromB
, contains all information fromB
. Of course, with a well-thought design, this doesn't happen, because even without inheritance,A
would contain all information inB
.One more issue would be the use of
dynamic_cast
orstatic_cast
, which you wouldn't encounter in an inheritance-free environment, but these can also be avoided even using inheritance.唯一的运行时影响可能是内存和速度方面的性能。考虑到功能方面,一切都可以在没有继承的情况下完成,唯一的问题是它相对于其他替代方案的性能如何。这将取决于您想要比较的具体场景以及编译器生成的代码。
The only runtime impact could be performance in terms of memory and speed. Considering functionality-wise everything can be done without inheritance, the only question is how well it performs as opposed to the alternatives. That will depend on the specific scenarios you want to compare, and the complier's generated code.
继承会对数据局部性产生负面影响,当您有大量数据需要处理时,这是一个大问题。与使用组合相比,您对数据布局的控制也更少,因此您的对象可能会占用更多内存。
如果您还使用多态性,那么当您引用虚拟函数表时,您会在间接函数调用上花费额外的周期,并且会获得更糟糕的数据局部性。
一般来说,面向对象编程的开销成本相当小,只有在处理大量数据时才需要考虑它。查看 Sony 的 面向对象编程的陷阱 演示文稿 — 它着眼于 OOP 性能游戏开发者的视角。
Inheritance can negatively impact data locality, which is a big deal when you have a lot of numbers to crunch. You also get less control over data layout than when you use composition, so your objects might take up more memory.
If you also use polymorphism, then you spend additional cycles on indirect function calls and get even worse data locality, as you reference virtual function tables.
Generally, the overhead cost of object-oriented programming is fairly small and you only have to think about it when you are processing large amounts of data. Check Sony's Pitfalls of Object Oriented Programming presentation — it looks at OOP performance from a game developer's perspective.
在阅读了其他(信息丰富!)的回复后,我相信还没有提到一个潜在的负面影响:
继承通常用于实现多态性。在 C++ 中,这意味着您传递对基本类型的引用(C++ 引用或指针),而不是按值传递,以避免 切片问题。在实践中,传递引用通常意味着对象的范围不应再定义其生命周期 - 因此人们开始使用动态内存管理(例如,
new
和delete
) 。 这个本身就可以打开一整罐蠕虫。长话短说:继承常常与动态内存分配齐头并进,这引发了一系列全新的问题。
After reading the other (informative!) responses, I believe one potential negative impact wasn't mentioned yet:
Inheritance is often used to achieve polymorphy. In C++, this means that you pass references (C++ references or pointers) to the base type around, instead of passing it by value, to avoid the slicing problem. In practice, passing references around often means that the scope of an object should no longer define its life time - so people start using dynamic memory management (say,
new
anddelete
). And this can open a whole can of worms itself.To make a long story short: very often, inheritance goes hand in hand with dynamic memory allocation, which opens a whole new class of issues.
由于您使用
C++
标记了您的帖子,我想补充一点,当您在C++
中使用虚拟函数时,最重要的运行时影响之一与无法扩展有关他们内联。事实上,对性能影响最大的并不是虚函数表查找,而是因为即使将虚函数声明为内联,编译器也无法扩展它。这会阻止重要的优化,而优化可能会使您的代码更快。
Since you tagged your post with
C++
, I'd like to add that one of the most important runtime impact when you use virtual function inC++
is related to the impossibility to expand them inline.In fact, the heaviest performance impact is not due to the virtual function table lookup, but to the fact that the compiler cannot expand a virtual function even if you declare it as
inline
. This prevents an important optimization that could make your code much faster.我认为继承只会改善运行时间。如果您在多个地方重写代码,则必须多次编译代码。
I would think inheritance would only improve runtime. If you rewrite the code in several places that code has to be compiled that many times more.