构造函数的作用

本文详细解析了C#中构造函数的作用及使用方法,特别是默认构造函数和空参数构造函数的重要性,并通过具体示例展示了如何在类继承中正确使用构造函数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

构造函数主要用来初始化对象。它又分为静态(static)和实例(instance)构造函数两种类别。大家应该都了解如果来写类的构造函数,这里只说下默认构造函数的作用,以及在类中保留默认构造函数的重要性。实际上,我说错了。正确的说法是:以及在类中保留空参数构造函数的重要性。

我们来写一个类A,代码如下:

public class A

{

   public int Number;       //数字

   public string Word;       //文本

}

//Test类中实例化

public class Test

{

    static void Main()

{

       A a = new A(); //实例化,A()即为类A的默认构造函数

     Console.WriteLine(“Number = {0}"nWord = {1}”,a.Number,a.Word);

       Console.read();

}

}

输出的结果是:

Number = 0

Word =

在上列示例中,我们并没有在A类中明确的写出构造函数,当我们没有提供任何构造函数时,C#自动为类提供了一个默认构造函数,其格式为:

public A()

{

   //空白的方法体

}

这个默认构造函数看起来似乎根本没什么作用,没有接收任何输入参数,方法体也是个空的。那么它真的是无所事事,可有可无的一个东西吗?我们回想下前面所讲的构造函数的主要作用,对,它主要用来初始化对象。看下输出结果,int类型的Number被初始化为默认值0string类型的Word被初始化为默认值空白字符,这些工作都是由看似没起作用的默认构造函数所完成的。

很快,A类的设计让我们并不满意,我们加强了它的能力,自己提供了构造函数:

public class A

{

    public int Number;     

    public string Word;     

    public A(int number,string word)

{

   Number=number;    //标记1

   Word=word;       //标记2

}

}

//Test类也重新设计

public class Test

{

static void Main()

{

        A a = new A(100,”一百”); //调用了新的带参数构造函数

      Console.WriteLine(“Number = {0}"nWord = {1}”,a.Number,a.Word);

        Console.read();

}

}

输出结果:

Number = 100

Word = 一百

运行很顺利,结果正确。当我们提供了构造函数时,C#认为我们应该是意识到、并且有能力来做好类的初始化工作,于是它将默认的构造函数撤销,将控制权交到了我们手里。我们自己的构造函数能胜任默认构造函数的工作吗?带着怀疑,我们做个尝试,将类A构造函数的方法体清除,即注释掉标记12行,重新运行,输出的结果是:

Number =0

Word =

这个结果和调用默认构造函数的结果是一样的,这证明我们自己提供的构造函数能担当默认构造函数的工作。

不久以后,业务进一步扩展,我们要新构一个类,这个类继承自类A,我们把它称为类B

public class A

{

    public int Number;     

    public string Word;     

    public A(int number,string word)

{

   Number=number;  

   Word=word;    

}

}

public class B:A

{

    public string Name;   //增加一个成员

    public B(int number,string word)

{

   Number = number;

   Word = word;

}

}

//修改Test

public class Test

{

   static void Main()

{

       B b = new B(100,”一百”);

       Console.WriteLine(“Number = {0}"nWord = {1}”,b.Number,b.Word);

       Console.Read();

    }

}

运行后出错,错误信息是:“A”方法没有采用“0”个参数的重载。为什么会这样呢?看起来我们并没有什么错误呀。A类提供了构造函数,B类也提供了构造函数。你满腹委屈,含泪望着比尔盖茨。老比怒目圆睁,啪的给你一巴掌:“A类还没构造好,你让我怎么给你构造B类!”。A类?构造?A类还要构造吗?你莫名奇妙了。

事实上,B类要完成构造,必须先完成A类的构造。当我们采用:

public B(int number,string word)

来构造B类时,由于没有明确指明继承的构造方法,C #默认我们继承自默认构造函数。

public B(int number,string word)base()

采用这条构造函数时,C# 先调用类A的默认构造函数base()完成基类的构造,然后调用B类的构造函数完成针对B类构造的剩余工作。尝试修改上面的相应代码段为:

//在类A中添加一个空参构造函数

public class A

{

     ……

     public A()

     {

         Number =1;

         Word=”空参构造”;

     }

     …….

}

//将类B构造函数改为继承A类空参构造

public B(int number,string word):base()

实际上,我是多此一举了,public B(……):base()public B(……)是一样的,未显式指明构造函数的继承体时,C#就默认为base()

输出结果

Number=100

Word = 一百

注意看我们给A类添加的空参构造函数,我们在方法体内给Number赋值1,给Word赋值“空参构造”。然而从输出结果看,这些赋值都被覆盖了。这就说明,base()在前,而后才是public B(…..)

回头来看我们那个错误的例子。遗憾的是,我们在类A中自己提供了构造函数,这导致A类的默认构造函数消失了,当B类从A类继承默认构造函数时,找不到入口了,这就导致了如上的错误。如果要避免错误,有两种方法:1、在A类中添加一个无参数的构造函数。2B类构造函数显式继承A类的构造函数。

事情已经解释的很清楚了,不过也许还有个小问题,就是:在B类中,我们提供了一个和A类构造函数结构相同的构造函数,为什么C#不能自动识别,自动继承呢?

道理很简单,C#不能靠猜测来判断我们提供的参数究竟是要用作初始化基类还是继承类。还是来看一个例子:

public class A

{

   public int Number;

   public string Word;

    public A(int number,string word)

    {

        Number = number;

        Word = word;

    }

}

public class B:A

{

    public string Name;

    public B(int number,string word,string name):base(number,word)

    {

        Number = number;

        Word = word;

        Name = name;

    }

}

public class Test

{

    static void Main()

    {

        B b = new B(100,”一百”,”初始化B的参数”);

        Console.WriteLine(“Number = {0}"nWord = {1}"nName = {2}”,

              b.Number,b.Word,b.Name);

        Console.Read();

}

}

输出结果是:

Number = 100

Word = 一百

Name = 初始化B的参数

注意在B类的构造函数中,我们提供了三个参数,其中前两个用于初始化A类中的成员,第三个用于初始化B类的成员。虽然父类构造函数与子类构造函数的参数数量不一样,然而由于我们明确的指定了继承的关系,它们很好的完成了工作。

### 构造函数作用与功能 构造函数在编程中的作用主要是为对象的初始化提供支持,确保对象在创建时能够处于一个有效且可用的状态。以下是构造函数的主要功能和作用: - **对象初始化**:构造函数的核心功能是对新创建的对象进行初始化。例如,在定义一个类时,可以通过构造函数为对象的成员变量赋初值[^3]。这意味着当对象被实例化时,其状态已经被正确设置,从而避免了未初始化的状态。 - **自动调用**:构造函数会在对象创建时自动执行,无需显式调用。这种机制保证了每个对象在创建时都会经过初始化过程[^1]。 - **灵活性与重载**:许多编程语言支持构造函数重载(如 Java 和 C++),允许通过不同的参数列表来实现多样化的初始化方式。这使得开发者可以根据实际需求选择合适的构造函数来初始化对象[^2]。 - **资源分配**:在某些情况下,构造函数还可以用于分配必要的资源,例如打开文件、分配内存或建立网络连接等。这些操作通常需要在对象生命周期的早期阶段完成,以确保对象能够正常工作。 - **封装性增强**:通过将初始化逻辑集中到构造函数中,可以提高代码的可维护性和可读性。开发者无需在多个地方重复编写初始化代码,而是统一由构造函数处理。 ```python class Example: def __init__(self, value): self.value = value # 初始化成员变量 # 创建对象时,构造函数自动执行 obj = Example(42) print(obj.value) # 输出: 42 ``` --- ### 不同语言中的构造函数特点 - **Python**:构造函数名为 `__init__`,在对象创建时自动调用。它主要用于初始化对象的属性,并支持灵活的参数传递[^1]。 - **Java**:构造函数名称与类名相同,支持重载以适应不同的初始化需求。此外,Java 还提供了默认构造函数(无参构造函数)[^2]。 - **C++**:构造函数同样与类名相同,支持重载和复制构造函数。复制构造函数用于通过已有的对象初始化新对象。 - **ABAP**:区分普通构造函数和静态构造函数。静态构造函数用于初始化类级别的静态属性,而普通构造函数则用于实例级别的初始化[^4]。 --- ### 总结 构造函数是面向对象编程中的重要概念,其主要作用是为新创建的对象提供初始化支持。通过构造函数,可以确保对象在创建时具备正确的初始状态,同时还能分配必要的资源。不同编程语言对构造函数的具体实现可能有所差异,但核心思想是一致的:在对象创建时完成初始化任务。 ---
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值