5.3
构造函数和析构函数构造函数和析构函数是类中比较特殊的两种成员函数,主要用来对对象进行初始化和回收对象资源。一般来说,对象的生命周期是从构造函数开始,以析构函数结束。如果一个类含有构造函数,在实例化该类的对象时就会调用构造函数,如果含有析构函数则会在销毁对象时调用它。构造函数的名字和类名相同。析构函数和构造函数的名字相同,但析构函数要在名字前加一个波浪号(~)。当退出含有该对象的成员时,析构函数将自动释放这个对象所占用的内存空间。
5.3.1
构造函数构造函数用于执行类的实例的初始化,每个类都有构造函数,即使没有声明它,编译器也会自动地为我们提供一个默认的构造函数。在访问一个类的时候,系统将最先执行构造函数中的语句。实际上,任何构造函数的执行都隐式地调用了系统默认提供的构造函数base()。在使用构造函数时应注意以下问题:
■ 构造函数的名字必须与类同名。
■ 构造函数没有返同类型,可以带参数,也可以不带参数。
■ 一般地,构造函数总是public类别的。如果是private类型的,表明类不能被实例化,这通常用于只含有静态成员的类。
■ 构造函数的主要作用是完成对类的初始化工作,在构造函数中不要做对类的实例进行初始化以外的事情,也不要尝试显式地调用构造函数。
下面我们列举了几种类型的构造函数。
默认构造函教不带参数的构造函数称为“默认构造函数”(其实也是实例构造函数中的一种)。如果一个类不包含任何实例构造函数声明,则会自动地为该类提供一个默认实例构造函数。默认构造函数只是调用直接基类的无参数构造函数。如果直接基类没有可访问的无参数实例构造函数,则编译时发生错误。对于一个抽象类,它的默认构造函数的声明可访问性是受保护的。而对于非
抽象类,它的默认构造函数的声明可访问性是公共的。因此,默认构造函数始终为下列形式:
//默认构造函数.C为类的名称
protected C():base(0{}
//或
public C():base(){}
在下面的示例中:
class Person
{
string name;
int age
}
由于类不包含任何实例构造函数声明,因此就为它提供一个默认构造函数。因而,此示例完全等效于:
class Person
{
string name;
int age;
public Person():base(){}
}
实例构造函数实例构造函数用于创建和初始化实例所需操作的成员,创建新对象时将调用类构造函数,例如:
class Person
{
string name;
int age;
public Person(string name,int age)//带有两个参数的实例构造函数
{
this.name=name;
this.age=age;
}
}
无论何时创建基于Person类的对象,都会调用此构造函数,并且将所需的数据成员通过参数传递的方式将其初始化,以便可以为数据成员指定初始值。实例构造函数是不能继承的,因此一个类除了自己声明的实例构造函数外,不可能有其他实例构造函数。
【例5.3】创建一个控制台应用程序项目,声明一个Person类并为这个类声明一些类成员,通过系统自动提供的默认构造函数和自已定义的实例构造函数来说明构造函数如何初始化实例所需的成员(Ch05Ex03)。
(1)首先新建一个控制台应用程序项目,在代码编辑器中打开源文件Program.cs,在命名空间中声明一个内部类Person,代码如下:
class ClassPerson
{
private string name;
private int age;
public ClassPerson(){}
public ClassPerson(string name,int age) //实例构造函数,在构造类实例的同时给字段赋值
{
this.name=name;
this.age=age;
}
public string Name
{
get{return name;}
set{name=value;}
}
public int Age
{
get{return age;}
set{age=value;}
}
}
(2)在Program类的Main方法中编写以下代码:
ClassPerson classPersonA=new ClassPerson(); //调用默认构造函数
ClassPerson classPersonB=new ClassPerson(“Jack”,20); //调用实例构造函数
Console.WriteLine(“classPersonA.Name:{0}\t classPersonA.Age:{1}”,classPersonA.Name,classPersonA.Age);
COnsole.WriteLine(“classPersonB.Name:{0}\t classPersonB.Age:{1}”,classPersonB.Name,classPersonB.Age);
(3)可按”Ctrl+F5”组合键编译并运行程序,最后程序的结果如图5.6所示。
由程序的结果可以看出,第一个classPersonA对象调用的是默认的构造函数,我们并没有对成员进行初始化,而是系统用默认值来初始化对象字段,例如:string被初始化为空字符串,int被初始化为0。而clasaPersonB对象调用的是实例构造函数,通过构造函数的参数传递给对象字段而进行初始化,所以就有上面结果。