使用虚函数virtual:
当调用一个对象的函数时,系统会去检查这个对象定义的类,即声明类,看所调用的函数是否是虚函数 ,如果不是虚函数,那么它就直接执行该函数。而如果有virtual关键字,那么它就不会立刻执行该函数了,而是检查对象的实例类 ,实例类里,他会检查这个实例类的定义中是否有重新实现的虚函数(通过override关键字),如果有,则马上执行该实例类中的这个重新实现的函数。而如果没有,系统会不停地往上找实例类的父类,并对父类重复刚才在实例类里的检查,直到找到第一个重载了该虚函数的父类为止,然后执行该父类里重载后的函数。
例如:
A是基类,有一个Move(翻译:移动)虚函数,B继承A,C继承B(如果屡不清画个图)
B重写A的虚方法, base.Move();如果加上此句就是使用此虚方法(基类)并且可以加上
B类独有的其它方法
B重写A的虚方法, 如果不加base.Move(); 那么就完全重写
C继承B 也可以重写A的虚函数 并且因为继承关系,可以使用父类继承的方法(C可以用A的方法)
代码如下====================================================
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class A //假设A为基类
{
//基类有个移动方法
public virtual void Move()
{
Debug.Log("移动中....");
}
public void Talk()
{
Debug.Log("我真帅!!");
}
}
public class B:A//B继承A
{
public override void Move()
{
base.Move();//使用父类的方法
//也可以写一些需要添加的东西,实现了移动,而且实现了子类独有的移动后的效果
Debug.Log("走路发光");
}
}
public class C:B//C继承B
{
public override void Move()//重写父类的方法
{
Debug.Log("C");
base.Move();
//此处不使用父类的方法,完全重写了父类方法
}
}
public class D : C
{
//D继承C依然可以用C继承的A也就是D的爷爷辈
public override void Move()
{
base.Move();
}
}
public class GameManager_0 : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
B b = new B();
b.Move();
Debug.Log("========================");
C c = new C();
c.Move();
Debug.Log("========================");
D d = new D();//D继承了C C继承了A D等于间接继承了A
d.Talk();
}
// Update is called once per frame
void Update()
{
}
}
===================================================================
效果
虚函数和一般函数的区别:
一般函数编译时就静态的编译到了执行文件中,其地址在程序运行期间是不发生变化的,而虚函数在编译期间不是静态编译的,它的相对地址并不确定,它会根据运行时期对象实例来动态判断要调用的函数。