C# 创建子类的实例是否会创建父类的实例?

C# 创建子类的实例是否会创建父类的实例?,c#,.net,C#,.net,我是C#的新手,我想知道,如果我创建一个子类的实例,它会自动创建父类的实例吗 这是我的密码: class Program { public class ParentClass { public ParentClass() { Console.WriteLine("ChildClass uses my Ctor "); } } public class ChildClass : Paren

我是C#的新手,我想知道,如果我创建一个子类的实例,它会自动创建父类的实例吗

这是我的密码:

class Program
{

    public class ParentClass
    {
        public ParentClass()
        {
            Console.WriteLine("ChildClass uses my Ctor ");
        }

    }

    public class ChildClass : ParentClass
    {
        public ChildClass()
        {
            Console.WriteLine("SaySomething");
        }
    }

    public static void Main()
    {
        ChildClass child = new ChildClass();
    }
}
它是否也会自动创建父类的实例

不是一个单独的例子;当谈到继承时,
ChildClass
是一个
ParentClass
实例

换句话说,这就像:

创建狗时,我们是否也创建动物的实例


我们不创造狗,也不(分别)创造动物;狗就是动物的例子。如果我们创建一只卷毛狗,卷毛狗就是狗,也是动物。

不,它不是,但它调用基构造函数(父类的构造函数)。在您的情况下,它是空的,因此对基类构造函数的调用由编译器为您完成:

class Program
{
    public class ParentClass
    {
        public ParentClass()
        {
            Console.WriteLine("ChildClass drived from me ");
        }

    }

    public class ChildClass : ParentClass
    {
        public ChildClass() : base() // base() call is voluntary
        {
            Console.WriteLine("This also use my Ctor");
        }
    }

    public static void Main()
    {
        ChildClass child = new ChildClass();
    }
}
但是,如果基类没有无参数构造函数,则必须调用它

class Program
{
    public class ParentClass
    {
        public ParentClass(string foo)
        {
            Console.WriteLine("ChildClass drived from me ");
        }

    }

    public class ChildClass : ParentClass
    {
        public ChildClass() : base("some foo") // base call is obligatory
        {
            Console.WriteLine("This also use my Ctor");
        }
    }

    public static void Main()
    {
        ChildClass child = new ChildClass();
    }
}
根据定义,当
ChildClass
继承表单
ParentClass
时,
ChildClass
对象也属于
ParentClass

如果你的命名更贴近现实生活,那么就更容易理解

class Animal {}
class Cat : Animal {}

var rocky = new Cat();

瞧,洛奇是一只猫,但它也是一种动物。

不,它只会创造一个儿童班。

你问题的实际答案是

“否”,它是子类的实例,而不是父类的实例

但如果您的问题是:“您是否有一个包含父类所有属性的实例对象”,答案是

“是”,您将拥有中的所有属性和字段 父类复制到子实例中


具体谈论您的代码:

class Program
{

    public class ParentClass
    {
        public ParentClass()
        {
            Console.WriteLine("ParentClass constructor is called");
        }

    }

    public class ChildClass : ParentClass
    {
        public ChildClass()
        {
            Console.WriteLine("ChildClassConstructor is called");
        }
    }

    public static void Main()
    {
        //will print that the Parent ctor is called, followed by printing that the child ctor is called
        ChildClass child = new ChildClass();

        //will print that the Parent ctor is called, followed by printing that the child ctor is called
        ParentClass childinparentbox = new ChildClass();

        //will print that the Parent ctor is called
        ParentClass parent = new ParentClass();

        //At this point there are 3 object instances in memory


        //by the way, this can't be done. Can't store a parent in a child: a parent is-not-a child
        ChildClass parentinchildbox = new ParentClass();


    }
}
我更改了消息,使其与提出的观点相关:

构造函数只是一种方法,在创建新对象时强制调用它。您可以使用它来设置新对象以供使用,初始化属性等。类在C#中是分层的-所有东西都是某个东西的子类,有时是对象。您的父类是Object的子类,它只是没有说明。您的孩子被声明为父母的孩子

正如其他人所指出的,当您使用
new
时,您不会得到多个对象实例,您只会得到一个您要求创建的对象实例。子类总是可以引用/“存储在”声明为父类型的变量中。这是因为事物在Child->Parent的方向上有一个“is-a”关系。狗是动物,猫是动物,动物是物体。他们没有相反的关系。。你不能普遍地说汽车是法拉利,或者某种动物是狗

因此,事情会追溯到层次结构,您可以将猫或狗存储在声明为容纳动物的变量中。动物可能有一个GetNumberOfLegs()方法,用于报告腿的数量。猫和狗各返回4个,猴子返回2个

面向对象编程的一个关键原则是,您可以以通用的方式引用事物;所有动物都有一定数量的腿。如果是动物中存储的猫/狗,则GetNumberOfLegs()返回4,如果是猴子,则返回2。。但是如果你只对腿的数量感兴趣,你不需要特别知道它是猫、狗、猴子。这将在接下来的讲座中详细介绍,所以我不需要在这里深入讨论。我把这个细节作为一个解释,解释为什么我们甚至想要有一个层次结构,有一个动物,创建一只狗,并将它存储在一个类型为Animal的变量中。我们这样做是因为我们经常想用一种通用的方式来指代事物,因为我们不关心细节;我们定义了我们所关心的一般事物,而具体的事物则符合模型。你可以开车;你不需要专门学习如何驾驶福特或雪佛兰-他们的方向盘和踏板在同一个位置/布置。您可以操作通用接口。你不在乎转向是如何实现的——液压、齿轮齿条、转向垂臂——你只在乎当你“像这样”转动方向盘时,汽车会“像那样”转动

回到你问的问题:

因为Child是一个Parent是一个对象,所以当您创建一个新的Child时,您将看到一个打印输出,指示调用了父构造函数,另一个指示调用了子构造函数。这并不意味着已经在计算机内存中创建了两个对象——构造函数是按正向(从根到尖端)顺序调用的,用于层次结构中的所有对象,从Object开始,然后是Parent,然后是Child。这是因为在任何构造函数的代码中,第一件事就是调用相关的父构造函数。构造函数代码中的第一件事是调用它的父级

因此,运行时从子代开始,然后到达父代、祖父母、曾祖父母,一直到祖先的顶端,然后返回,按照从上到下的顺序在每个构造函数中运行其余的代码。这就是为什么看到调用父构造函数的打印输出,然后看到子构造函数


这都是一个相同的对象,是多个方法调用。看到两个打印输出并不是表示内存中有两个对象,而是一个对象和两个方法(两个构造函数方法),它们以递归顺序被调用。i、 从这个类创建的对象实例应该有这个实现逻辑。创建一个类的实例,获取所有逻辑并将其转换为对象的行为。当您从某个类继承时,基本上是将父类的实现逻辑包含在子类的模板中,因此您只需要得到一个扩展的“模板”。当你创造
class Coffee {}

class Cappucino : Coffee {}