类的构造函数

构造函数是类的特殊方法,在使用new关键字创建类对象时被间接的调用,和普通的方法不同的是,类的构造函数是没有返回值的,连一个void都没有,并且构造函数的名字和类名相同。

因为构造函数也是类的方法,所以构造函数也支持方法的重载。如果我们在定义一个类的时候没有显示的为它定义构造函数,C#将为我们提供一个默认的构造函数。默认的构造函数没有参数,它的访问权限是public的,它将确保类的所有字段数据都被设置为正确的默认值。

1 class Car
2 {
3   public string petName;
4   public int currSpeed;
5 }

当创建一个Car的实例时,默认构造函数将被调用,并设置petName的值为null,currSpeed的值为0.

1 Car car = new Car();

当然,默认构造函数它所能作的事情是有限的,这时我们可以重新定义类的构造函数,从而达到我们想要的目的。如下为Car类自定义了一个构造函数:

 1 class Car
 2 {
 3   public string petName;
 4   public int currSpeed;
 5
 6   public Car(string petName, int currSpeed)
 7   {
 8       this.petName = petName;
 9       this.currSpeed = currSpeed;
10   }
11 }        

一旦定义了自定义构造函数,默认构造函数就被自动从类中移除了,这时的new Car();将会引起编译器错误: “Car”不包含采用“0”个参数的构造函数。

如果我们希望使用默认构造函数和自定义构造函数来创建类的实例的话,就必须也提供显式的默认构造函数才可以。

在C#中有一个this关键字(上面的代码已经用到了),这个关键字用在构造函数上可以实现一种叫构造函数链的用法。当我们为类定义了多个构造函数时,这个模式就会很有用。我们来看代码:

 1 class Car
 2 {
 3     public string petName;
 4     public int currSpeed;
 5
 6     public Car()
 7     {
 8         this.petName = "myCar";
 9     }
10     public Car(int currSpeed)
11     {
12         if (currSpeed > 100) currSpeed = 100;
13         this.currSpeed = currSpeed;
14     }
15     public Car(string petName, int currSpeed)
16     {
17         this.petName = petName;
18
19         if (currSpeed > 100) currSpeed = 100;
20         this.currSpeed = currSpeed;
21     }
22 }

上面的代码中存在验证逻辑的代码冗余,这时使用串联法来重新定义,让那个接收参数最多的构造函数来充当主构造函数,在这个构造函数中实现必要的逻辑验证,其余的构造函数使用this关键字把传入的参数转发给主构造函数,并提供所有必要的其他参数就可以了,我们改进一下上面的代码:

 1     class Car
 2     {
 3         public string petName;
 4         public int currSpeed;
 5
 6         public Car()
 7         {
 8             this.petName = "myCar";
 9         }
10         public Car(int currSpeed) : this("", currSpeed) { }
11         public Car(string petName, int currSpeed)
12         {
13             this.petName = petName;
14
15             if (currSpeed > 100) currSpeed = 100;
16             this.currSpeed = currSpeed;
17         }
18     }

使用这个技术可以帮助我们简化编程任务,真正的工作将由那个主构造函数来完成,其他构造函数只是将“皮球”踢给了这个主构造函数。那么我们来看以下他的调用顺序是怎样的, 我们使用只有一个参数的构造函数来创建类的实例:如下

 1     class Car
 2     {
 3         public string petName;
 4         public int currSpeed;
 5
 6         public Car()
 7         {
 8             this.petName = "myCar";
 9         }
10         public Car(int currSpeed) : this("", currSpeed) { Console.WriteLine("只有一个参数的构造函数。"); }
11         public Car(string petName, int currSpeed)
12         {
13             Console.WriteLine("有两个参数的构造函数。");
14             this.petName = petName;
15
16             if (currSpeed > 100) currSpeed = 100;
17             this.currSpeed = currSpeed;
18         }
19     }
1 static void Main(string[] args)
2 {
3     Car car = new Car(90);
4
5     Console.ReadLine();
6 }

这时输出的结果如下:

有两个参数的构造函数。
只有一个参数的构造函数。

结果很明显,我们在给构造函数传入一个参数时,编译器调用只有一个参数的构造函数,这时这个构造函数又将参数发送给了主构造函数,最终是由主构造函数完成实例化(其实可理解为是一个参数的构造函数又调用了主构造函数),主构造函数完成后返回到最初调用的构造函数里,并执行剩下的代码。

C#还支持静态构造函数,静态构造函数适用于初始化在编译时未知的静态数据的值。下面是关于静态构造函数的几点说明:

  • 一个类只能有一个静态构造函数,也就是说静态构造函数不能被重载;
  • 静态构造函数不允许有访问修饰符,并且不接受任何参数;
  • 不管创建多少个类的实例,静态构造函数只执行一次(在创建类实例或首次访问静态成员之前,静态构造函数会被调用);
  • 静态构造函数的执行先于任何实例级别的构造函数。

如果一个类的构造函数的访问修饰符被定义为private,则这个类将不能被用来实例化对象。

时间: 2024-08-01 08:21:45

类的构造函数的相关文章

【C++学习之路】派生类的构造函数(二)

二.有内嵌对象的派生类 1.一般来说,我们会这样定义构造函数 student( int i, string nam, int pid, string pnam, int sid) : person( i, nam),parent(pid,pnam){ stuid = sid; } person是基类的构造函数,parent是该派生类内嵌的person子对象   2.具体例子 1 #include <iostream> 2 using namespace std; 3 class A 4 { 5

ThinkPHP中的__initialize()和类的构造函数__construct()

ThinkPHP中的__initialize()和类的构造函数__construct()网上有很多关于__initialize()的说法和用法,总感觉不对头,所以自己测试了一下.将结果和大家分享.不对请更正.首先,我要说的是1.__initialize()不是php类中的函数,php类的构造函数只有__construct().2.类的初始化:子类如果有自己的构造函数(__construct()),则调用自己的进行初始化,如果没有,则调用父类的构造函数进行自己的初始化.3.当子类和父类都有__co

对C++中派生类的构造函数和析构函数的认识

一:构造函数 形式:派生类名::派生类名:基类名1(参数1),基类名2(参数2),--基类名n(参数n),数据成员1(参数1),数据成员2(参数2),--数据成员n(参数n){ 各种操作的说明 } 执行过程:先执行基类的构造函数,再进行数据成员的赋值,最后执行函数体. 其中基类名和数据成员的顺序是由在派生类的定义中声明的顺序决定执行的顺序的,因此它们的顺序是任意的,但为了可读性,还是最好按顺序写. 如果基类只有默认构造函数,则基类名和参数表可以不用写出来. 二:复制构造函数 派生类的构造函数的形

C++构造函数 &amp; 拷贝构造函数 &amp; 派生类的构造函数 &amp; 虚继承的构造函数

构造函数 ,是一种特殊的方法 .主要用来在创建对象时初始化对象, 即为对象成员变量赋初始值,总与new运算符一起使用在创建对象的语句中 .特别的一个类可以有多个构造函数 ,可根据其参数个数的不同或参数类型的不同来区分它们 即构造函数的重载.(摘自百度百科构造函数). 一.最基本的构造函数 1 class Base 2 { 3 public: 4 Base(int var) : m_Var(var) 5 { 6 } 7 private: 8 int m_Var; 9 }; 以上构造函数的执行过程:

c++学习笔记5,多重继承中派生类的构造函数与析构函数的调用顺序(二)

现在来测试一下在多重继承,虚继承,MI继承中虚继承中构造函数的调用情况. 先来测试一些普通的多重继承.其实这个是显而易见的. 测试代码: //测试多重继承中派生类的构造函数的调用顺序何时调用 //Fedora20 gcc version=4.8.2 #include <iostream> using namespace std; class base { public: base() { cout<<"base created!"<<endl; }

面向对象:有关类和构造函数的基础知识

1.类和对象对象:具体存在的,可以被描述的实体 属性和行为类:具有共同属性和相同行为的多个对象的抽象 对象:具体的 实体类:抽象的 概念 类是对象的抽象 对象是类得具体实例 2.创建和使用类访问修饰符 [可选修饰符]class 类名{//类成员 //字段 > 数据 //属性 > 对字段的封装 //索引器 > 对集合类型字段的封装 //方法 > 对象的特殊行为 //事件 > 行为 //构造函数 > 初始化 } 字段:访问修饰符 数据类型 变量名; 使用:a.创建对象类名

scala入门教程:scala中的面向对象定义类,构造函数,继承

我们知道scala中一切皆为对象,函数也是对象,数字也是对象,它是一个比java还要面向对象的语言. 定义scala的简单类 class Point (val x:Int, val y:Int) 上面一行代码就是一个scala类的定义: 首先是关键字class 其后是类名 Point 类名之后的括号中是构造函数的参数列表,这里相当于定义了对象的两个常量,其名称分别为x,y,类型都是Int 上面的类和下面的类是一致的,不过更精简了. class Point (xArg:Int, yArg:Int)

c++中派生类的构造函数

Son(char *n, int *b, int g, char *add, int *gir, double s) : Father(n, b, g) 派生类构造函数名(总参数列表):基类构造函数名(参数列表) {派生类中新增数据成员初始化语句} 冒号前面的部分是派生类构造函数的主干,基类的构造函数想同,但它的总参数列表中包括基类构造函数所需要的参数和对派生类新增的数据成员初始化所需参数 冒号后面的部分是要调用的基类构造函数及其参数

C++:派生类的构造函数和析构函数

4.2 派生类的构造函数和析构函数4.2.1 派生类构造函数和析构函数的执行顺序 通常情况下,当创建派生类对象时,首先执行基类的构造函数,随后再执行派生类的构造函数:当撤销派生类对象时,则先执行派生类的派生类的析构函数,随后再执行基类的析构函数. //例4.5 派生类的构造函数和析构函的执行顺序 #include<iostream> using namespace std; class Base{ //声明基类Base public: Base() { cout<<"Co

实战基础技能(02)-----------类,属性,构造函数和方法打死都要快速区分

一:做项目时经常会看见很对自定义的类,一定要快速的识别才能正确的理解项目代码 二:区分 类:很好区分,有Class修饰 方法:有返回值的描述,新的方法名 构造函数:没有返回值,有类名 属性:主要是get 和set标志,可能会有自定义的类型有一定的迷惑性 实战基础技能(02)-----------类,属性,构造函数和方法打死都要快速区分,布布扣,bubuko.com