gpt4 book ai didi

How does polymorphism with multiple inheritance work in assembly?(多态性和多重继承在程序集中是如何工作的?)

转载 作者:bug小助手 更新时间:2023-10-28 11:55:20 24 4
gpt4 key购买 nike



so I believe I understand polymorphism with single inheritance, where say you have classes Dog and Cat inherit from an interface Animal and Animal has a Speak and Walk function so then you generate v tables for Dog and Cat, both having a function pointer to their respective Speak and Walk functions, and if I’m calling a general one of those functions for a general Animal, assembly will grab the first data member of the Animal which is a pointer to the v table, dereference it, then add the correct offset to get the correct function pointer, then call said function at the memory address.

所以我相信我理解单继承的多态,假设你有Dog和Cat类,Animal继承自一个接口Animal和Animal有一个Speech和Walk函数,所以你为Dog和Cat生成v表,这两个表都有一个指向它们各自的Speech和Walk函数的函数指针,如果我为一般的Animal调用这些函数中的一个通用函数,汇编将获取Animal的第一个数据成员,它是指向v表的指针,取消对它的引用,然后添加正确的偏移量以获得正确的函数指针,然后在内存地址调用所述函数。


So my question is how would this work for multiple inheritance. So for the example, I will do Dog and Cat inheriting from interfaces Animal and Colorable: Animal will have functions Speak and Walk, and Colorable will have GetColor and SetColor. Would Dog have have a v table to Animal functions and then a v table to Colorable functions? Would that mean that every Colorable class would have memory padding so that way its v table is the second member so that you can do polymorphism with Colorable? Or would you have a triple pointer pointing to a table of v table pointers so that you only have class instances of the memory padding as opposed to object instances? Wouldn’t dereferencing a triple pointer be slow?

所以我的问题是,这将如何适用于多重继承。例如,我将从接口Animal和Colorable继承Dog和Cat:Animal将具有函数Speak和Walk,Colorable将具有GetColor和SetColor。Dog会有一个v表给Animal函数,然后有一个v表给Colorable函数吗?这是否意味着每个Colorable类都有内存填充,这样它的v表就是第二个成员,这样你就可以用Colorable做多态了?或者你会有一个三重指针指向一个v表指针的表,这样你就只有内存填充的类实例,而不是对象实例?解引用一个三重指针不会很慢吗?


Is there another memory schema that I’m not considering? I haven’t found many good resources on this.

有没有其他我没有考虑过的记忆模式?我在这方面没有找到很多好的资源。


I know C#, Java, Rust, etc. supports polymorphism with multiple inheritance, so I feel like this is a solved thing.

我知道C#、Java、Rust等支持多重继承的多态,所以我觉得这是一个可以解决的问题。


I have tried searching on YouTube and stack overflow and Google, none of which have given me good results. I did find a page regarding Java doing multiple inheritance but to me it was kind of cryptic and hard to understand.

我试着在YouTube、Stack Overflow和谷歌上搜索,但都没有给我带来好的结果。我确实找到了一个关于Java执行多重继承的页面,但对我来说,它有点神秘,很难理解。


Edit:
To add clarification, I’m looking specifically for single layered inheritance, like Rust’s trait syntax. Regarding C# and Java multiple inheritance, I am referring to the ability to use multiple interfaces for an object and be able to use said interface as a type for static polymorphism. Rust allows for implementing multiple traits.

编辑:为了补充说明,我专门寻找单层继承,比如Rust的特征语法。关于C#和Java多重继承,我指的是对一个对象使用多个接口的能力,并能够将该接口用作静态多态的类型。锈病允许实现多种特征。


更多回答

None of those languages support multiple inheritance in the way you're suggesting. C# does not support multiple inheritance of classes, but it does support multiple inheritance using interfaces. Multiple Inheritance is ... inherits more than one superclass. Java does not support Multiple Inheritance; Rust also does not use class inheritance so problems like diamond patterns cannot exist... Perhaps try revisiting how single-inheritance is implemented in these languages. The semantic inconsistency of multiple class inheritance is why implementations of it are generally avoided.

这些语言都不支持您所建议的多重继承。C#不支持类的多重继承,但它支持使用接口的多重继承。多重继承是..。继承多个超类。Java不支持多重继承;Rust也不使用类继承,因此不存在像钻石模式这样的问题……或许可以重新回顾一下单继承是如何在这些语言中实现的。多类继承的语义不一致是通常避免实现它的原因。

@EdNutting in my question, I used interfaces instead of classes or abstract classes. Rust uses the trait system as opposed to interfaces or classes that you can inherit, but replace Animal and Colorable with traits and you can have a Vec<dyn Animal> and Vec<dyn Colorable>. Java you can implement multiple interfaces, C# as well. And you can do static polymorphism with all these implementations. I guess I’m specifically looking at Rust’s implementation where inheritance can only be one layer deep, to avoid diamond cases.

@EdNutting在我的问题中,我使用了接口,而不是类或抽象类。Rust使用特征系统,而不是你可以继承的接口或类,但用特征替换Animal和Colorable,你就可以拥有Vec和Vec。Java你可以实现多个接口,C#也可以。您可以使用所有这些实现进行静态多态。我想我特别关注Rust的实现,其中继承只能深入一层,以避免出现钻石情况。

If I recall correctly, Stroustrup covers how this is (can be) done in his The C++ Programming Language, but I don't remember the details - it's complicated. Your understanding of how inheritance and virtual methods work in single inheritance is correct, and with multiple interfaces you have a VMT for each interface.

如果我没记错的话,Stroustrup在他的The C++ Programming Language中涵盖了如何(可以)完成这一点,但我不记得细节了-它很复杂。您对继承和虚方法如何在单继承中工作的理解是正确的,对于多接口,每个接口都有一个VMT。

Thank you for the resource. It seems like a really good book. I managed to skim through Section 21-22 which cover class hierarchy and multiple inheritance and unfortunately does not discuss how it works under the hood as far as I can tell.

感谢您提供的资源。这似乎是一本非常好的书。我设法浏览了第21-22节,其中涵盖了类层次结构和多重继承,不幸的是,就我所知,并没有讨论它是如何在幕后工作的。

This essentially runs headlong into a terminology problem - you're saying "inheritance" but the proper word is "implement". Implementing multiple interfaces is not the same thing as inheriting from multiple classes.

这实际上直接遇到了一个术语问题--您说的是“继承”,但正确的词是“实现”。实现多个接口与从多个类继承不是一回事。

优秀答案推荐

None of the languages you say implement inheritance in the way you describe. You are describing C++ - it's in C++ you have a pointer to vtable at the beginning of a class.

您所说的语言都没有以您所描述的方式实现继承。您描述的是C++--在C++中,在类的开头有一个指向vtable的指针。


In C++, the first base class gets merged with the derived: the vtable pointer in the beginning of the Dog is also a vtable pointer for the inscribed Animal base class (if Animal is first). The vtable would start with Animal virtual functions (Speak, Walk), then other base classes functions (GetColor, SetColor), then other virtual finctions of Dog, if any.

在C++中,第一个基类与派生的合并:Dog开头的vtable指针也是内切的Animal基类的vtable指针(如果Animal是第一个)。Vtable将从Animal虚拟函数(Speech、Walk)开始,然后是其他基类函数(GetColor、SetColor),然后是Dog的其他虚拟函数(如果有的话)。


All other base classes will have a different vtable. That means the inscribed Colorable vtable pointer will point to a different vtable of Dog - the one that has GetColor and SetColor first. Moreover, those virtual functions will not be the same as the ones in the main vtable! They would be a special versions, that correct the pointer first (to point on Dog instance, instead of the inscribed Colorable instance).

所有其他基类都将具有不同的vtable。这意味着内嵌的可着色vtable指针将指向Dog的另一个vtable-首先具有GetColor和SetColor的那个vtable。此外,这些虚拟函数将不会与主vtable中的函数相同!它们将是一个特殊的版本,首先更正指针(指向Dog实例,而不是内嵌的可着色实例)。


In Java, there is a vtable for each base interface, and the runtime does a search in the list of interfaces to find a correct one. It is pretty much the same in C#, with minor differences. The JIT-compiler can optimize that, if needed.

在Java中,每个基本接口都有一个vtable,运行时在接口列表中进行搜索以找到正确的接口。这在C#中基本相同,只是有一些细微的不同。如果需要,JIT编译器可以对其进行优化。


In Rust, there are no pointers to vtable inside the "classes" at all. Instead, Rust uses "fat pointers" for the interfaces themselves - references to the interface are double sized, because they contain two pointers: one for the object, one for the vtable. The pointer to the vtable is only produced when you convert an object to a &dyn Interface type - not before. The pointer points to the correct position inside the vtable, so the current interface functions will appear first:

在Rust中,在“类”中根本没有指向vtable的指针。相反,Rust对接口本身使用“胖指针”--对接口的引用是双倍大小的,因为它们包含两个指针:一个用于对象,一个用于vtable。指向vtable的指针仅在您将对象转换为&dyn Interface类型时才会产生-而不是在此之前。指针指向vtable内的正确位置,因此当前接口函数将首先出现:



  • &dyn Animal will be equal {&Dog, &Dog_vtable + 0},

  • &dyn Colorable will be equal {&Dog, &Dog_vtable + 16}, etc


更多回答

C# compiles it into intermediate language by which point the interface and class information has been fully resolved (notwithstanding dynamic loading.) The backend of the compiler ("JIT") typically forms a single vtable for each concrete class. There's no need of "searching through a list of vtables". AFAIK, the JIT for Java solved this the same way a long time ago (circa 2010.) (Side note: This is why the myth of interfaces be slow no longer holds.) Re C++: stackoverflow.com/questions/33556511/…

C#将其编译为中间语言,此时接口和类信息已完全解析(尽管动态加载)。编译器的后端(“JIT”)通常为每个具体类形成单个vtable。不需要“在vtables列表中搜索”。AFAIK,Java的JIT很久以前(大约2010年)就解决了这个问题。(Side注:这就是为什么接口慢的神话不再成立的原因。)Re C++:stackoverflow.com/questions/33556511/.

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com