构造器(constructor)
1.是类型的成员之一
2.狭义的构造器指的是实列“构造器”
3.如何调用构造器
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace gouzaoqi
{
internal class Program
{
static void Main(string[] args)
{
Student stu1 = new Student();
//调用无参构造
Console.WriteLine(stu1.ID);
Console.WriteLine(stu1.Name);
Console.WriteLine("=====================================================");
Student stu2 = new Student(6, "yuan");
//调用有参构造
Console.WriteLine(stu2.ID);
Console.WriteLine(stu2.Name);
Console.WriteLine("=====================================================");
Student stu3 = new Student();
stu3.stu();
//Student.stu();
Console.WriteLine(stu3.ID);
Console.WriteLine(stu3.Name);
}
}
class Student
{
public int ID;
public String Name;
public void stu()
{
this.ID = 8;
this.Name = "缘";
//int ID = 5;
// String Name = "缘";
}
public Student(int id, String name)
{
this.ID = id;
this.Name = name;
}
public Student()
{
this.ID = 2;
this.Name = "原";
}
}
}
Student stu1 = new Student(); 这句语句就是在调用构造器
有参构造和无参构造的区别在于是否必须传参
(ctor后连续敲两次tab会自动构造一个构造器出来)
4.声明构造器
class Student
{
public int ID;
public String Name;
public void stu()
{
this.ID = 8;
this.Name = "缘";
//int ID = 5;
// String Name = "缘";
}
//有参构造器的使用
public Student(int id, String name)
{
this.ID = id;
this.Name = name;
}
//无参构造器的创建
public Student()
{
this.ID = 2;
this.Name = "原";
}
}
(ctor后连续敲两次tab会自动构造一个构造器出来)
5.构造器的内存原理
无参构造
前面第一列的内存编号代表计算机自己的运行内存
假设第二列是栈内存,后面的三列是堆内存
黄色代表被其他的方法所占用的栈内存,绿色代表stu所占的栈内存(分配地址时是高地址往低地址分配)
当执行到Student stu1 = new Student();这句的new操作符就在堆里面寻找可以分配的一个空间
由于Student这个构造器里面有int和string两种类型一共要占用4+4个字节,所以在堆内存中会划分八个字节去存储这个student这个实列
当new分配的堆内存分配好后就开始调用Sudent(),这个构造器将之前的堆内存切割给int类型和string类型,并将两个类型进行初始化
初始化结束后将堆内存地址返回给栈内存
有参构造
前面构造部分和无参部分一至,区别在于给int类型和string类型初值时,由于是给了参数所以在堆里面是直接存放传入的参数(string类型为引用类型存放的也是一个地址,还需要再去堆内存中找一个地方存储字符,并将地址返回给string)
方法的重载(Overload)
例子
Console。WriteLine()这个方法就存在着方法重载
声明带有重载的方法
方法的签名由方法的名称、类型形参的个数和它的每一个形参(从左到右的顺序)的类型和种类(值、引用或输出)组成。方法签名不包含返回类型。
即定义的方法名字和参数的种类个数不一样即可重载
class chongzai
{
public int add(int a,int b)
{
return a + b;
}
public double add(double a, int b)
{
return a + b;
}
public int add(int a, int b,int c)
{
return a + b+c;
}
public int add<Y>(int a,int b)
{
return a + b;
}
}
实列构造函数签名由它的每一个形参(从左到右的顺序)的类型和种类(值、引用或输出)组成
重载决策(调用哪一个重载):用于在给定了参数列表和一组候选函数成员的情况下,选择一个最佳函数成员来实施调用。
using System;
namespace fangfachongzai
{
class Program
{
static void Main(string[] args)
{
chongzai Add = new chongzai();
double sum1 = Add.add(1,3);
double sum2 = Add.add(7.7,3);
double sum3 = Add.add(7,3,3);
Console.WriteLine(sum1);
Console.WriteLine(sum2);
Console.WriteLine(sum3);
}
}
class chongzai
{
public int add(int a,int b)
{
return a + b;
}
public double add(double a, int b)
{
return a + b;
}
public int add(int a, int b,int c)
{
return a + b+c;
}
public int add<Y>(int a,int b)
{
return a + b;
}
}
}
会根据传入参数的不同自己去匹配最佳的方法
如何进行debug
设置断点
点击这句的空白地方生成断点,再次点击断点消失
观察方法调用时的call stack
代表了这一行调用了这个方法
Step-in,Step-over,Step-out
走进方法里面,一句一句往下读
可以跳过这次调用去到下一个语句
执行完子函数余下部分,并返回到上一层函数。
观察局部变量的值与变化
方法的调用与栈
方法调用时栈内存的分配
对stack frame的分析
stack frame代表的是一个方法在被调用时在栈内存调用的布局
关于压入栈的数据是谁主导谁负责,当酶促调用结束栈就会一步一步的释放。