C#虚⽅法详解(⼀切尽有,建议收藏)
前⾔:通过这篇⽂章可以将C#中的虚⽅法理解透彻,讲的⾮常详细,⼗分推荐刚⼊门的⼩伙伴收藏嗷
⽬录:
⼀、虚⽅法的概念
在C#中,虚⽅法就是可以被⼦类重写的⽅法,如果⼦类重写了虚⽅法,则在运⾏时将运⾏重写的逻辑;如果⼦类没有重写虚⽅法,则在运⾏时将运⾏⽗类的逻辑。虚函数在编译期间是不被静态编译的,它的相对地址是不确定的,它会根据运⾏时期对象实例来动态判断要调⽤的函数,其中那个申明时定义的类叫申明类,那个执⾏时实例化的类叫实例类。虚⽅法是⽤virtual关键字声明的
A a =new B();其中A是申明类,B是实例类。
⼆、虚⽅法的特点
1. 虚⽅法前不允许有static,abstract,或override修饰符
2. 虚⽅法不能是私有的(因为在⼦类中要进⾏重写),所以不能使⽤private修饰符
3. 不能在声明虚⽅法的同时指定重写虚⽅法,因为重写⽅法只能重写基类的虚⽅法,也就是要提前在基类中声明虚⽅法,所以virtual关
键字和override关键字不能同时使⽤。
三、虚⽅法的作⽤
1. 允许派⽣类(即其⼦类)对⽗类进⾏扩展。
2. 虚⽅法是多态特性的⼀种体现。
3. 增加开发过程中的可维护性,条理清晰明了。
四、虚⽅法的声明
在⽗类中:
public virtual返回类型⽅法名()
{
⽅法体;
}
在⼦类中:
public override返回值类型⽅法名()
{
base.⽗类⽅法;
⽅法体;
}
五、虚⽅法的执⾏
⼀般⽅法在编译时就静态地编译到了执⾏⽂件中,其相对地址在程序运⾏期间是不发⽣变化的,也就是写死了的!
虚函数在编译期间是不被静态编译的,它的相对地址是不确定的,它会根据运⾏时期对象实例来动态判断要调⽤的函数。
具体的检查流程如下:
1. 当调⽤⼀个对象的⽅法时,系统会直接去检查这个对象申明定义的类,即申明类,看所调⽤的⽅法是否为虚⽅法。
2. 如果不是虚函数,那么它就直接执⾏该函数。如果有virtual关键字,也就是⼀个虚⽅法,那么这个时候它就不会⽴刻执⾏该函数了,
⽽是转去检查对象的实例类。
3. 在这个实例类⾥,它会检查这个实例类的定义中是否有实现该虚⽅法(通过new关键字)或是否有重新实现该虚⽅法(通
过override关键字),如果有,那么OK,它就不会再了,⽽马上执⾏该实例类中的这个重新实现的⽅法。⽽如果没有的话,系统就会不停地往上实例类的⽗类,并对⽗类重复刚才在实例类⾥的检查,直到到第⼀个重载了该虚⽅法的⽗类为⽌,然后执⾏该⽗类⾥重载后的⽅法。
下⾯我们通过具体实例看看:
例1:
class A
{
public virtual void Getreturn()
{
Console.WriteLine("我是A类的虚⽅法");
}
writeline函数}
class Program
{
static void Main(string[] args)
{
A a =new A();//定义⼀个a这个A类的对象,这个A就是a的申明类,实例化a对象,A是a的实例类
a.Getreturn();
Console.ReadLine();
}
}
过程:1.先检查申明类A 2.检查到是Getreturn是虚拟⽅法 3.转去检查实例类A,结果是它本⾝ 4.执⾏实例类A中实现Getreturn的⽅法 5.输出结果我是A类的虚⽅法
例2:
class A
{
public virtual void Getreturn()
{
Console.WriteLine("我是A类的虚⽅法");
}
}
class B : A
{
public override void Getreturn()//重新实现了虚⽅法
{
Console.WriteLine("我是B类重写后的⽅法");
}
}
class Program
{
static void Main(string[] args)
{
A a =new B();//定义⼀个a这个A类的对象,这个A就是a的申明类,实例化a对象,B是a的实例类
a.Getreturn();
Console.ReadLine();
}
}
过程:1.先检查申明类A 2.检查到是虚拟⽅法 3.转去检查实例类B,有重写的⽅法 4.执⾏实例类B中的⽅法 5.输出结果我是B类重写后的⽅法
例3:
Console.WriteLine("我是A类的虚⽅法");
}
}
class B : A
{
public override void Getreturn()//重新实现了虚⽅法
{
Console.WriteLine("我是B类重写后的⽅法");
}
}
class C : B
{
}
class Program
{
static void Main(string[] args)
{
A a =new C();//定义⼀个a这个A类的对象,这个A就是a的申明类,实例化a对象,C是a的实例类
a.Getreturn();
Console.ReadLine();
}
}
过程:1.先检查申明类A 2.检查到是虚拟⽅法 3.转去检查实例类C,⽆重写的⽅法 4.转去检查类C的⽗类B,有重写的⽅法5.执⾏⽗类B中的Getreturn⽅法 6.输出结果我是B类重写后的⽅法
例4:
class A
{
public virtual void Getreturn()
{
Console.WriteLine("我是A类的虚⽅法");
}
}
class B : A
{
public new void Getreturn()//覆盖⽗类⾥的同名函数,⽽不是重新实现
{
Console.WriteLine("我是B类New⽅法");
}
}
class Program
{
static void Main(string[] args)
{
A a =new B();//定义⼀个a这个A类的对象,这个A就是a的申明类,实例化a对象,B是a的实例类
a.Getreturn();
Console.ReadLine();
}
}
过程:1.先检查申明类A 2.检查到是虚拟⽅法 3.转去检查实例类B,⽆重写的(这个地⽅要注意了,虽然B⾥有实现Getreturn(),但没有使⽤override关键字,所以不会被认为是重写) 4.转去检查类B的⽗类A,就是它本⾝ 5.执⾏⽗类A中的Getreturn⽅法 6.输出结果我是A类的虚⽅法
例5:
Console.WriteLine("我是A类的虚⽅法");
}
}
class B : A
{
public new void Getreturn()//覆盖⽗类⾥的同名函数,⽽不是重新实现
{
Console.WriteLine("我是B类New⽅法");
}
}
class Program
{
static void Main(string[] args)
{
B b =new B();//定义⼀个b这个B类的对象,这个B就是b的申明类,实例化b对象,B是b的实例类
b.Getreturn();
Console.ReadLine();
}
}
过程:1.先检查申明类B 2.检查到不是虚拟⽅法 3.执⾏B类⾥的Getreturn() 4.输出结果我是B类New⽅法
可以使⽤抽象⽅法重写基类中的虚⽅法
class A
{
public virtual void Getreturn()
{
Console.WriteLine("A类的虚⽅法");
}
}
abstract class B : A
{
public abstract override void Getreturn();//使⽤override修饰符,表⽰抽象重写了基类中该函数的实现
}
abstract class C : A
{
public abstract new void Getreturn();//使⽤new修饰符显式声明,表⽰隐藏了基类中该函数的实现
}
密封类可以重写基类中的虚⽅法(基类中的虚⽅法将隐式的转化为⾮虚⽅法,但密封类本⾝不能再增加新的虚⽅法)
Console.WriteLine("A类的虚⽅法");
}
}
sealed class Program:A
{
public override void Getreturn()
{
Console.WriteLine("Program类重写后的⽅法");
}
static void Main(string[] args)
{
Program p =new Program();
p.Getreturn();
Console.ReadLine();
}
}
六、虚拟类的规则
1. 虚拟类其实指的是正常类中的虚拟⽅法,所以虚拟类可以直接使⽤实例
2. 虚拟⽅法是在⽅法前加virtual关键字
3. 虚拟函数与正常函数没有区别
4. ⼦类继承虚拟类可以实现虚拟⽅法也可以不实现虚拟⽅法。(实现=重写⽅法)
基类中使⽤虚⽅法,在⼦类中重写的时候,有时想⽤基类中的⽅法时,可以使⽤base关键字调⽤
通过阅读这篇⽂章你收获了不少吧,给博主点波赞吧!有不⾜之处可以提出来,评论区见

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。