C#-CLR在继承过程中如何组织内存/引用?
假设我有如下代码片段:(澄清目的/格式不正确) 使用base关键字调用父类构造函数 在这种情况下,继承是如何组织的?我有以下一些不好的假设: 由于Manager是从Employee派生的,所以Manager类用(empID、empName、ssn)填充 步骤1:构造函数调用:base(“1”、“sam”、“xxx”) 步骤2:基类(Employee)构造函数填充派生类字段(empID、empName、ssn) 步骤3:branchID由派生类构造函数赋值 我的问题是C#-CLR在继承过程中如何组织内存/引用?,c#,.net,oop,inheritance,C#,.net,Oop,Inheritance,假设我有如下代码片段:(澄清目的/格式不正确) 使用base关键字调用父类构造函数 在这种情况下,继承是如何组织的?我有以下一些不好的假设: 由于Manager是从Employee派生的,所以Manager类用(empID、empName、ssn)填充 步骤1:构造函数调用:base(“1”、“sam”、“xxx”) 步骤2:基类(Employee)构造函数填充派生类字段(empID、empName、ssn) 步骤3:branchID由派生类构造函数赋值 我的问题是 如果一个类是从基类派生的
IIRC,杰夫·里克特(Jeff Richter)在某种程度上谈到了这一切——这是这类事情的一个很好的信息来源。你可以把对象想象成有“插槽”,可以在其中放入方法和字段。。。基类将有用于字段的插槽1、2、3,并且,比如说,一个方法有插槽4。如果创建派生类,新字段将添加另一个插槽(例如插槽5) 这样,使用基类类型的变量仍然可以访问正确的字段,而不必担心差异。派生类的构造函数必须首先调用基类构造函数,即使您没有在代码中显式指定它 如果slot-4方法是虚拟的,并且派生类重写了它,则将重写方法再次放入slot-4,如果隐藏它(通过
new
),它将分配一个新的slot(因此只能通过派生类的变量调用它)
我就是这么想的。这是一种简化的方法,但它有帮助。我想它可能是一个内存块,但话说回来,这是一个实现细节。(来源:) 是的,派生类还将在内存中包含基类字段。杰弗里·里克特(Jeffrey Richter)通过C#在CLR第112页上说: 然后,M3执行其代码来构造Manager对象。这将导致在托管堆中创建管理器类型的实例,即管理器对象,如图4-9所示。如您所见,管理器对象和所有对象一样具有类型对象指针和同步块索引此对象还包含必要的字节,用于将管理器类型定义的所有实例数据字段保存为管理器类型的任何基类(在本例中为Employee和object)定义的任何实例字段。(重点添加) 还值得注意的是,会为任何基本类型创建一个单独的内存块。但仅为类型数据创建一个内存块(因此最多只能创建一次)。当您创建一个管理器对象(从Employee派生)时,CLR将确保堆上有一个管理器类型对象,以及一个员工类型对象 1) 雷德蒙:微软出版社,2006年。
()第110-116页相关讨论。哇!感谢您的关心和花时间解释细节。我真的很感谢您。
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");
}
-----------------
Manager
-----------------
empID
empName
ssn
branchID