C# 某个类的新创建的对象以何种方式引用其派生的类?

C# 某个类的新创建的对象以何种方式引用其派生的类?,c#,C#,由于每个类都是从system.object派生的,派生类对象是否引用了其层次结构中的类?当然,只有在他们之上的班级 例如 public class A { //contains some attributes and methods } public class B: A { //contains some attributes and methods } public class C: B { //contains some attributes and methods } 现在,C类的

由于每个类都是从system.object派生的,派生类对象是否引用了其层次结构中的类?当然,只有在他们之上的班级

例如

public class A
{
//contains some attributes and methods
}

public class B: A
{
//contains some attributes and methods
}

public class C: B
{
//contains some attributes and methods
}

现在,C类的对象是指A、B以及system.OBJECT类吗?

C类的对象也是指B、A和system.OBJECT类型的对象


它将拥有它继承自的其他类的所有公共成员或受保护的方法、属性和字段。这就是为什么所有对象都有一个ToString方法——它们从System.Object继承它。

是。默认情况下,所有类都隐式引用system.object类。

不完全是这样,但它比任何其他类更具语义

类C的对象引用名为C的类定义的实例。但是,它可能是类型强制转换到类型A、B的对象中的类型,也可能只是普通的旧System.object

C和A/B/System.Object之间没有引用。它更像是将所有这些类定义合并成一个统一的C

这意味着您可以执行以下操作:

function void DoSomething(A input) { 
  // do something as A
}

C myObj = new C();

DoSomething(myObj);
function void DoSomething(C input) { 
  // do something as C
}

A myObj = new A();

DoSomething(myObj);
在上述情况下,C将在DoSomething调用中被类型强制转换为A类型的对象

您还可以执行以下操作:

public class A {
  public String MyValue { get; set; }
}

public class B : A{
  public String AnotherValue { get; set; }
}

public class C : B {
  public void DoSomething() {
    MyValue = "Hello";
    AnotherValue = "World";
  }

  public String Output() {
    return String.Format("{0} {1}", MyValue, AnotherValue);

  }
}

C myObj = new C();
C.DoSomething();
String message = C.Output();
// value of message will be "Hello World"
现在情况正好相反。您不能执行以下操作:

function void DoSomething(A input) { 
  // do something as A
}

C myObj = new C();

DoSomething(myObj);
function void DoSomething(C input) { 
  // do something as C
}

A myObj = new A();

DoSomething(myObj);

在这种情况下,您可能会遇到编译器错误。

阅读注释后,您的误解似乎是,当您创建类C的实例时,也会有类B、类a或类对象的单独实例。事实并非如此。有一个对象是类C的实例,它也可以被视为类B、类a的实例,或者在上读取的对象。修改Eric Lippert的类比:当狗出生时,它是狗、哺乳动物和动物。但是只有一只狗

考虑这种动物、哺乳动物、狗,而不是A、B、C:

public class Animal 
{ 
    void Breathe();
} 

public class Mammal : Animal
{ 
    void GrowHair();
} 

public class Dog
{ 
    void Bark();
} 
此继承链具有以下效果:

public class C
{
    void Breathe();
    void GrowHair();
    void Bark();
}

在字段方面,回到A、B、C,考虑如下:

public class A            
{            
    private int _a;
}            

public class B: A            
{            
    private int _b;
}            

public class C: B            
{            
    private int _c;
}   
实例在内存中的外观如何?一些字节的开销,加上四个字节的_a:

B的一个实例在内存中看起来如何?它看起来就像一个加上四个字节的实例:

OVERHEAD
_a : four bytes
_b : four bytes
OVERHEAD
_a : four bytes
_b : four bytes
_c : four bytes
C的一个实例看起来像A的一个实例,再加上八个字节:

OVERHEAD
_a : four bytes
_b : four bytes
OVERHEAD
_a : four bytes
_b : four bytes
_c : four bytes
开销是多少?毫不奇怪,这就是对象类定义的东西!因此,每次向继承链中添加另一个类时,该类中定义的字段都会固定在其父类的内存结构的末尾


派生类的实例不引用其父类定义的数据;它包含由其父类定义的数据。

我花了一段时间才弄明白。您认为C是一种原型继承语言。事实并非如此

在原型继承语言(如JavaScript)中,每个对象都有对其原型对象的引用。因此,在JavaScript中,您可能会说:

function Dog() {}
Dog.prototype.legs = 4;
var rover = new Dog();
var spot = new Dog();
spot.legs = 3; // Poor spot!
print(rover.legs); // 4
print(spot.legs); // 3
罗孚和spot都参考了Dog.prototype。当你问罗孚你有几条腿?罗孚说我不知道;让我问问我的原型。罗孚自身引用的对象引用了Dog.prototype引用的对象,该对象具有legs属性

当你问spot你有多少条腿时,spot也会提到它的原型,但它并不需要它,因为spot已经知道它有多少条腿了

再多做一点工作,我们就可以建立一个系统,其中Dog.prototype的原型是动物原型对象。然后这个链条会继续下去;漫游者将引用Dog.prototype,Dog.prototype将引用Animal.prototype,Animal.prototype将引用Object.prototype


C完全不是这样工作的。在JavaScript中,对象是原型链接列表的一部分,当需要查找属性时,将搜索原型链。在C语言中,每个属性的所有信息都存储在每个实例中。在C语言中,对象不引用其基类型的实例,也不包含其基类型的实例;相反,它继承其基类型的所有成员。除了构造函数和析构函数之外。

你所说的“引用”是什么意思?类C的对象将从类A和类B继承。请参见创建类C的对象的时间;然后首先创建类system.object的对象作为其最高级别的基类,并且必须将对该对象的引用发送到该引用的位置???,现在创建类a的对象,必须将对该对象的引用发送到该位置,然后在继承权之后,B类的对象创建了这个对象的地址,最后必须发送C类对象创建的地址,我这里的问题是所有这些引用是否都存储在C类的对象中??派生C的所有类的引用否。。只有一个实例,它是C类的
t对象是一个C,因此它也是一个B,一个a,一个System.object,因为这是C的一部分。换句话说,C类指的是B类,指的是a类,指的是System.object。因此,当你创建一个C类实例时,该实例只需要引用C类即可。@SanaZehra:如果你还有第二个问题,请打开另一个问题。但是,简单地说:是的;按从基到派生的顺序调用基类构造函数。但字段初始值设定项是按从派生到基的顺序运行的。但派生对象是否引用这些类b、a和system.object。。。我的意思是C类对象是否包含对内存中所有这些类的引用@SanaZehra:我认为人们对你的问题感到困惑,因为完全不清楚你指的是什么。假设你有一碗米饭。现在我问你们,你们的碗饭是指容器吗?米饭是指食物吗?你完全有理由要求我澄清这个问题。假设我问你,“白宫”这个词是指华盛顿特区彭斯利瓦尼亚大道1600号的同一所房子吗?这是一个更加明确的问题。你所指的是什么意思一点也不清楚;尝试使用白宫意义上的reference。它在内存中不是作为4个单独的对象存储的,而是作为一个对象存储的,该对象的定义是所有4个对象的成员的组合。金毛猎犬是狗,也是动物。当我说金毛寻回犬时,我不是指动物,我指的是一种特定类型的动物;然后首先创建类system.object的对象作为其最高级别的基类,并且必须将对该对象的引用发送到该引用的位置???,现在创建类a的对象,必须将对该对象的引用发送到该位置,然后在继承权之后,B类的对象创建了这个对象的地址,最后必须发送C类对象创建的地址,我这里的问题是所有这些引用是否都存储在C类的对象中??C所属的所有类的引用derived@SanaZehra当前位置白宫当然没有房子。这是一所房子。白宫是一所房子,它包含了椭圆形办公室,宾夕法尼亚大道1600号指的是白宫所指的同一所房子。你得到的是,指和包含所有的混淆;它们是非常不同的。但是那个派生对象是指这些类b、a和system.object吗。。。我的意思是C类对象是否包含对内存中所有这些类的引用。。非常感谢你!!!=这就是我想知道的。另外,当我在C类中没有提到任何默认的零参数化构造函数时,那么是A、B的默认构造函数,以及在我创建C对象时调用的SYSTEM.OBJECT@萨那萨拉:是的;如果您没有特别调用另一个基类构造函数,则会调用该基类的默认构造函数。@SanaZehra非常欢迎您。请投票选出你认为有用的答案,并接受最有用的答案。好的,非常感谢。你的解释帮助我找到了问题的答案@ErricLipert但仍然继承了构造函数,对吗。。就像我在派生类中不提供零参数化构造函数一样。。。已调用基类构造函数。@SanaZehra:构造函数未被继承。如果未能提供构造函数,则可以免费获得一个调用基类构造函数的构造函数(如果有的话)。您不继承基类构造函数;你叫它。