方法的由来
C++中用两个冒号访问命名空间
如:std::cout << "Hello,World!";
“方法”是一个面向对象的概念,当一个函数作为类的成员出现时,就被称之为方法
方法也可以称作“成员函数”
C++中对类的声明放在.h文件中,而类的定义放在.cpp文件中
c#中类的声明和定义是放在一起的
C++:在.h头文件中声明类,包括作为其成员的方法
C++中因为有main函数,所以函数可以单独声明
而C#、JAVA是纯面向对象语言,将非面向对象的内容抛弃了
函数只能作为类(或结构体)的成员声明,即方法
C#中方法的声明和定义不分家
声明(可称作方法头)与定义(可称作方法体)必须相连
方法的定义格式(方法头):
修饰符 返回值类型 函数名 参数列表
(红色为不可省略)
方法修饰符大全:
意义不冲突的修饰符可以组合在一起
方法命名规范
给方法命名必须用一个动词或动词短语
使用大驼峰命名
形式参数
参数以变量的形式参与到方法内算法逻辑的构成
形式参数是一种变量
待续:ref
static(静态)方法
直接隶属于这个类,而非隶属于实例对象的方法
总结:
调用方法:与C语言完全相同
函数名+圆括号
Name(); 括号内写参数,这里写进去的参数称作实际参数
写进去的实际参数必须与声明的形式参数列表对应(参数个数、参数类型、参数顺序)
声明方法时写的“参数”是parameter,全称formal parameter,形式参数
调用方法时写的“参数”是argument,实际参数
形参是变量,实参是值,C#是强类型语言,变量与值的类型必须匹配才能写入
构造器(构造函数)
是类型(type)的成员之一
构造器用来创建实例在内存当中的内部结构
在之前常用的创造实例的语句
class Student
{
public int ID;
public string Name;
}
Student stu = new Student();
student();就是构造器,输出发现创建的这个实例ID字段的值为0
当声明了类但没有为类准备构造器时,编译器会自动为其准备一个默认构造器
默认构造器会在内存中创建对象并将把类中的成员初始化
创建自定义构造器:
构造器方法的名称必须和类的名称一模一样!
class Student
{
this.ID = 1; //初始化字段值
this.Name = "No name"
}
public int ID;
public string Name;
}
带参数的构造器:
class Student
{
public Student(int initId , string initName)
{
this.ID = initId;
this.Name = initName;
}
public int ID;
public string Name;
}
当带参数的构造器声明好之后,不带参数的默认构造器Student()将无法使用
必须在括号内写上参数:
Student stu = new Student(2,“Mr.JK”);
构造器重载
重载:一个函数可以有多种定义,通过调用时输入的不同参数来切换不同定义
当既需要能赋初始值的带参数构造器,又需要不赋初始值的无参数构造器时,可使用重载
class Student
{
//第一定义 有参数
public Student(int initId , string initName)
{
this.ID = initId;
this.Name = initName;
}
//第二定义 无参数
public Student()
{
this.ID = 1;
this.Name = "No name";
}
public int ID;
public string Name;
}
Student stu = new Student(2,"Mr.Okay"); //此处调用有参数的第一定义
Student stu2 = new Student(); //调用无参数的第二定义
重载函数根据调用时输入的参数不同来选择执行不同的定义
创建构造器的快捷键
在类中创建构造器的VS快捷键:
输入ctor,然后按两下TAB键
就会自动出现一个构造器
构造器的内存原理
使用默认构造器时
student类有两个字段,其中ID是int类型,是占用四个字节的结构体类型
而Name是string类型,是引用类型,占用四个字节,存储的是引用的实例的地址
1.分配内存空间
使用默认的Student stu = new Student(); 时,stu是一个局部变量,应该存储在栈中
图中绿色为声明stu变量时为其准备的内存空间,现在还是空的,要等new操作符执行完后将实例地址存入
new操作符创建实例时在堆上开辟内存
该类的int字段占4字节,string字段占4字节,所以共开辟8个字节的存储空间
2.初始化
实例占用的内存空间分配好后,就要调用构造器函数了
构造器会按类型的字段切割分到的内存空间,默认构造器会将空间内值全部刷成0
string变量值都为0时,是NULL值
3.将地址存入引用变量
内存分配、初始化结束后,会将创建的实例地址存入引用变量stu
自定义构造函数
会在第二步初始化时将值存入实例的字段
string是引用变量,赋值时存的又是另一个实例的地址
方法的重载(Overload)
如图所示
Console类里有19个名字叫WriteLine的方法定义
方法名相同,但这19个方法的“方法签名”的不同,按上下键可以切换不同的重载定义,会显示不同的参数
只要方法签名不同,就可以同时定义同名方法作为重载!
方法签名
方法签名由
1.方法的名字
2.方法的类型形参(待续)
3.每一个参数(从左到右)的类型、种类(值、引用或输出)
组成,但方法的签名不包括方法的返回值类型、形参变量名!
错例1:
如图所示两个参数数量、类型、种类完全相同,但返回值类型不同的方法
这样两个方法是不能同时定义的!
错例2:
形参类型、数量、种类相同,但形参变量名不同,这样两个方法也不能同时定义!
再次强调:
构成方法签名的:方法名、类型形参(目前未接触)、从左到右每一个参数类型、种类
两个方法方法名相同,签名不同时,就可以重载
补充1:类型形参
使用在泛型方法中
参数的类型也参与到方法体组成的方法
public int Add<T>(int a, int b)
{
T t; //声明一个类型为T的变量
return a + b;
}
以上的<T>就是类型形参
类型形参参与构成方法签名
补充2:参数种类(引用传递、值传递)
public int Add(ref int a, int b)
{
return a + b;
}
以上不加额外修饰符的参数默认为值参数
若在参数类型前加上修饰符ref,就会将其转换为引用传递的参数
若在参数类型前加上修饰符out,就会将其转换为输出参数
称作参数的种类,参数的种类参与构成参数签名
实例构造器也可以使用重载,构造器的签名由方法名(与类型名相同的)、形参列表构成
重载决策
根据调用时传递进方法的参数的数量、类型来决定使用哪个方法定义
方法的debug(以VS中为例)
1.断点
在代码一行前面的空白点一下,设置断点后,在调试模式运行时,程序运行到这一行时会暂停,此时可以观察程序的状态,在VS中此时将鼠标放在任意一个变量上,会显示该变量当前的值
2.Call stack(调用栈)
“call stack”窗口会显示调用了断点所在语句的地方
有几层牵涉到断点的调用关系,call stack就有几层,就更深
可以称作调用栈
递归方法如果出现无限递归,调用栈就会越来越深,最后导致内存爆栈
3.Step into(步入、逐步执行)
快捷键为F11
单步执行,遇到子函数就进入并且继续单步执行
按F11键,跳转到当前选中的正在被调用的函数的函数体
每按一次F11,call stack窗口就会减少一层
(在调用关系上走到上一层,对调用关系抽丝剥茧)
“最细腻的debug方式”
4.Step over(步过)
快捷键为F10
在单步执行时,在函数内遇到子函数时不会进入子函数内单步执行,而是将子函数整个执行完在停止,也就是把子函数整个作为一步
遇到调用函数时,直接走完此函数得到结果
对确认无问题的函数,可以用F10跳过,对有怀疑的函数,可以按F11走进去逐步检查
“稍粗旷一些的debug方式”
5.Step out
在单步执行到子函数内时,用Step out就可以执行完子函数余下部分,并返回上一层函数。
6.观察局部变量的值的变化
在local窗口中可观察当前打有断点的函数内的局部变量的值
浙公网安备 33010602011771号