C# – CLR在inheritance期间如何组织内存/引用?

假设我有如下代码片段:( 澄清目的/没有很好地形成

class Employee { #region fields protected string _empID; protected string _empName; protected readonly string _ssn; #endregion public Employee(){} public Employee(string _empID,string _empName,string _ssn) { this._empID =_empID; this._empName=_empName; this._ssn = _ssn; } } class Manager : Employee { private string _branchID; public Manager(int _branchID):base(string _empID,string _empName,string _ssn) { this._branchID=_branchID; } } static void Main() { Manager mgr = new Manager("1","sam","xxx","Branch1"); } 

使用base 关键字我正在调用父类构造函数

在这种情况下,如何组织inheritance? 我有一些不好的假设如下:

由于Manager是从Employee派生的,因此Manager类中填充了(empID,empName,ssn)

 ----------------- Manager ----------------- empID empName ssn branchID 

第1步:构造函数调用:base(“1”,“sam”,“xxx”)

第2步:基类(Employee)构造函数填充派生类字段(empID,empName,ssn)

步骤3:branchID由派生类构造函数指定

…….

我的问题是

  • 如果一个类是从基类派生的,那么派生类也有基类的隐藏字段?
  • 派生类共享基类字段? 我是说为Base类和派生类分配了单独的内存块?
  • http://www.rvenables.com/linkjackandsufferaccidentaldroptable/clr_via_csharp_f4.9.png

    是的,派生类还将包含内存中的基类字段。 在CLR第112页通过C#,Jeffrey Richter说:

    “然后,M3执行其代码来构造一个Manager对象。这会导致在托管堆中创建一个Manager类型的实例,一个Manager对象,如图4-9所示。如您所见,Manager对象-as do all objects-具有类型对象指针和同步块索引。 此对象还包含将Manager类型定义的所有实例数据字段保存为Manager类型的任何基类定义的任何实例字段所需的字节数(在这种情况下,员工和对象) 。“ (强调添加)

    值得注意的是,为任何基类型创建了单独的内存块。 但仅适用于类型数据(最多只有一次)。 当您创建Manager对象(派生自Employee)时,CLR将确保堆上有Manager类型对象Employee Type对象

    1)里希特,杰弗里。 CLR通过C#。 雷德蒙德:微软出版社,2006年。( 亚马逊链接 )

    对象以标题开头,标题包含指向其实际类型信息的指针。 该类型信息包括用于确定哪种方法实际意味着什么的vtable 。 CLR在执行时使用该vtable来调用重写方法。

    对象头之后是与对象关联的所有实例数据 – 包括基类字段和派生类字段。 它只在一个地方 – 它不像派生类的实例也引用了基类的“隐藏”实例。 我强烈怀疑基类字段是第一位的,因为基类中的方法仍然可以通过对象“顶部”的偏移引用(在汇编中)到相同的字段…但是我没有任何东西在我面前证实这一点。

    IIRC,Jeff Richter的“CLR via C#”在一定程度上谈论了所有这些 – 它是这类事物的重要信息来源。

    您可以将对象视为具有“槽”,您可以在其中放入方法和字段…基类将具有用于字段的插槽1,2,3,并且,例如,方法具有插槽4.如果您创建在派生类中,新字段将添加另一个槽(例如,槽5)。

    这样,使用基类类型的变量仍然可以访问正确的字段而不必担心差异。 派生类的构造函数必须首先调用基类构造函数,即使您没有在代码中明确指定它。

    如果你的slot-4-method是虚拟的,你的派生类会覆盖它,你再次将override方法放在插槽4中,如果你隐藏它(通过new ),它会分配一个新槽(所以它只能通过一个变量来调用)衍生类的)

    那就是我怎么想的。 一种简化的方式,但它有所帮助。 我认为它可能是一个内存块,但话又说回来,这是一个实现细节。