如何在CLR中使用多重继承? [英] How to use multiple inheritance in the CLR?

查看:59
本文介绍了如何在CLR中使用多重继承?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了一些来源,例如声称在CLR中支持声称多重继承(多种基本类型)(但在C#和其他语言中不支持).根据本文描述的方法,似乎它比直接支持更像是一个技巧,但我仍然想知道它应该如何工作.

I have come across a few sources like this that claim multiple inheritance (multiple base types) is actually supported in the CLR (but not in C# and other languages). Based on the method described in this article, it seems it's more of a trick than a direct support, but still I wonder how it is supposed to work.

如果创建自定义VTable并在VTFixup中使用它实际上可以实现多重继承,那么如何在CIL中实际实现它并使用它呢?

If creating a custom VTable and using it in a VTFixup actually makes it possible to achieve multiple inheritance, how does one actually implement it in CIL and use it?

推荐答案

当前,CLR不支持多重继承.但是,事实证明(从标准c ++来看)编译器即使仅支持单个继承,也可以模拟多重继承.确实,这就是MC ++的作用.

Currently the CLR does not support multiple inheritance. However, it is proved (look at the standard c++) compiler that a compiler may emulate multiple inheritance even though it only supports single inheritance. Indeed, this is what the MC++ does.

理想情况下,您至少需要:

Ideally, you would at least need to:

  • 能够声明多重继承
  • 允许类型系统理解
  • 在覆盖方法时解决歧义
  • 处理构造函数和终结器

多重继承仿真

假设您要拥有一个继承自 B1 B2 类的类 A .说的课程是:

Suppose you want to have the class A that inherits from the classes B1 and B2. Say the classes are:

public class B1
{
    public void MethodDeclaredInB1();
}

public class B2
{
    public void MethodDeclaredInB2();
}

从概念上讲,编译器(通用编译器可以执行的操作)可以在后台执行以下操作:创建一个新类型,例如 A1 ,这是一个具有两个字段的简单对象.代码可能看起来像这样:

Conceptually, what the compiler (a generic compiler can do) can do the following under the hood: Create a new type, say, A1 which is a simple object with two fields. The code might look like this:

public sealed class A1
{
    public B1 B1;
    public B2 B2;
}

然后,在编译时,通过访问字段透明地转换调用:

Then, at compile time, transparently transform the calls by accessing the fields:

您的高级代码

A a = new A();
a.MethodDeclaredInB1();
a.MethodDeclaredInB2(); 

可以上交(暂时不考虑构造函数):

can be turned in (don't consider the constructor for now):

A1 a = new A1();
a.B1.MethodDeclaredInB1();
a.B2.MethodDeclaredInB2();

类型系统管理

这很困难,因为编译器无法使用该语言的标准规则,但是需要使用在编译时发出的辅助方法来执行类型检查.

This is tough, as the compiler cannot use the standard rules of the language, but needs to use helper methods emitted at compile time to perform the type checking.

您的高级代码

Object o = new A();
B1 b = o as B1;
b.MethodDeclaredInB1();

可以变成

Object o = new A1();
B1 b = AsOperator(o, typeof(B1));
b.MethodDeclaredInB1();

其中 AsOperator 方法可能是通用方法,请使用伪代码执行此操作:

where the AsOperator method could be a general purpose method the does this in pseudocode:

method AsOperator: instance i1 , type t1 -> returns instance of type t1
t2 <- get the runtime type of instance i1
if t2 is not a compiler generated object (e.g. A1) then
    use the standard type system checking (this is trivial and we skip it here)
else
    for each child type c1 in t2->parent classes
        if c1 is subtype of t1 or it is exactly the same as t1 then return the corresponding field (this is a trivial task too) and we are done

    no match, return null

AsOperator 还需要具有 CastOperator (功能相同,但不会返回null,而是引发 InvalidCastException ).这些新的运算符必须分布在代码中,因为编译器不能始终使用静态分析来确定对象实例的内容.

the AsOperator also requires having the CastOperator (which does the same, but instead of returning null, it throws InvalidCastException). these new operators must be spread across the code as the compiler cannot always use static analysis to determine what is the content of an object instance.

在覆盖方法时解决歧义这很麻烦,因为您必须解决钻石问题之类的问题.幸运的是,这是一个众所周知的问题,您可以找到一个解决方案(至少是次优的).调用继承方法和实例方法时,编译器需要修补 this 指针以定位正确的基类.

Resolve ambiguities when overriding methods This is a pain in the neck as you have to resolve problems like the Diamond Problem. Fortunately, this is a well-known problem, and you can find a solution (at least sub optimal). When invoking inherited and instance methods, the compiler needs to patch the this pointer to target the correct base class.

处理构造函数和终结器

构造函数是终结器,是特定的虚拟/继承方法.特别是,在C ++中,正在构造/销毁的对象的类型会随着时间的推移而变化,并在层次结构的末尾停止.即使不是很好的做法,在构造/销毁对象时也必须面对虚拟方法调用.

Constructors are finalizers are particular virtual/inherited methods. In particular, in C++ the type of the object being constructed/destructed changes over time, stopping at the end of the hierarchy. You have to face virtual method calls while constructing/destroying objects even though it is not good practice.

旁注

MC ++编译器发出一个使用这些概念的值类型,并覆盖运算符以具有所需的语义.

The MC++ compiler emits a value type that uses these concepts and overrides the operators in order to have the required semantics.

构建一个可以满足您要求的编译器很有挑战性,但确实非常困难,因为您首先必须为所有新情况定义适当的行为(例如,考虑钻石问题),而好处可能是有限的.使用接口而不是类,可能有助于避免多重继承.

Building a compiler that does what you ask is challengingm interesting, but truly hard as you first have to define a proper behaviour for all the new cases (think of the diamond problem for example), while the benefit might be limited. Using interfaces instead of classes, might help in avoiding multiple inheritance.

这篇关于如何在CLR中使用多重继承?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆