五、方法的定义、调用与调试
方法的由来
c语言中的函数
C++中的函数
当函数以类的成员出现的时候,就变成了方法了
C#和java是纯面对对象的语言,已经把非面对对象的部分都抛弃了
示例:
namespace CSharpFun {
internal class Program {
static void Main(string[] args) {
}
}
//计算圆的面积,圆柱的体积,圆锥的体积
class Calculator {
//计算圆的面积
public double GetCircleArea(double r) {
return Math.PI * r * r;
}
//计算圆柱的体积
public double GetCylinderVolume(double r, double h) {
return GetCircleArea(r) * h;
}
//计算圆锥的体积
public double GetConeVolume(double r, double h) {
return GetCylinderVolume(r, h) / 3;
}
}
}
方法的定义与调用
C++中方法的声明和定义是分开的
调用方法会传入实参,并且传入的实参需要与该方法所定义的形参匹配
namespace CSharpFun {
internal class Program {
static void Main(string[] args) {
Calculator cal = new Calculator();
double res = cal.GetCircleArea(5);
Console.WriteLine(res);
}
}
//计算圆的面积,圆柱的体积,圆锥的体积
class Calculator {
//计算圆的面积
public double GetCircleArea(double r) {
return Math.PI * r * r;
}
//计算圆柱的体积
public double GetCylinderVolume(double r, double h) {
return GetCircleArea(r) * h;
}
//计算圆锥的体积
public double GetConeVolume(double r, double h) {
return GetCylinderVolume(r, h) / 3;
}
}
}
构造器
namespace ConstructorExample {
internal class Program {
static void Main(string[] args) {
Student student = new Student();
Console.WriteLine(student.ID);
Console.WriteLine(student.Name);
Console.WriteLine("===========================");
Student student2 = new Student(2, "nihao");
Console.WriteLine(student2.ID);
Console.WriteLine(student2.Name);
}
}
class Student {
public int ID;
public string Name;
public Student() {
this.ID = 1;
this.Name = "No Name";
}
public Student(int initID, string initName) {
this.ID = initID;
this.Name = initName;
}
/*
* 构造器没有返回类型
* 可以有多个构造器,但是构造器的形参必须不同
* 快速写出构造器的方法,打出ctor,然后按两下Tab键
*/
}
}
构造器的内存原理
栈分配内存是从比较高的地址往比较低的地址分配的,直到分配到栈顶,没有内存可分配了,这个时候栈就溢出了
这一部分的内存讲解很重要
/* * 首先在堆中创建int,然后给ID赋值,并转成二进制,存入堆中, * 然后创建string,因为string是引用类型,所以还要去堆中找一个位置 * 存储字符串转成的二进制形式,然后把这块地址,返回给Name,然后把ID 和 Name * 的地址返回给栈中的对象 */
方法的重载
重载方法的示例:
Console.WriteLine(100); Console.WriteLine("hello,world"); Console.WriteLine(1000L); Console.WriteLine(2.0D); //以上这些就是方法的重载 //重载,就是方法的名字是相同的,但是传入的参数个数、类型、顺序等等不同(总的来说就是方法的签名不同)
方法重载的示例:
起初,我们只需要知道,方法签名,包含名字,和参数列表,方法签名不一样,就可以构成重载
namespace OverloadExample { internal class Program { static void Main(string[] args) { Console.WriteLine("Hello, World!"); } } class Calculator { public int Add(int a, int b) { return a + b; } public int Add(int a, int b, int c) { return a + b + c; } //类型的形参不一样 public int Add<T>(int a, int b, int c) { return a + b + c; } //参数的种类不一样 //使用的是引用参数 public int Add(ref int a, int b) { return a + b; } public double Add(double a, double b) { return a + b; } }
根据传入的参数,来决定,调用哪一个方法
对方法Debug
Call Stack就像是一个记录方法调用的栈,可以非常直观的看到调用关系
方法的调用与栈
stack frame方法被调用的时候在内存中的布局
这部分的演示可以反复观看
也可以看这篇文章