虚函数
namespace Test { class CA { public virtual void Foo() { Console.WriteLine("CA.Foo"); } } class CB : CA { public override void Foo() { Console.WriteLine("CB.Foo"); } } class Test { public static void InvokeFoo(CA ca) { ca.Foo(); } public static void Main() { InvokeFoo(new CB()); } } }
|
这里InvokeFoo()方法的参数类型是CA,但是传给它的参数是new CB(),这是一个CA ca=new CB()的问题,ca的指向其实是堆上CB的对象。
输出结果:CB.Foo
另外一种情况:
去掉基类的virtual和派生类的override
namespace Test { class CA { public void Foo() { Console.WriteLine("CA.Foo"); } } class CB : CA { public void Foo() { Console.WriteLine("CB.Foo"); } } class Test { public static void InvokeFoo(CA ca) { ca.Foo(); } public static void Main() { InvokeFoo(new CB()); } } }
|
问题:
本以为输出结果:CB.Foo
但是输出结果为:CA.Foo
原因:
于关键字virtual的存在,它会告诉编译器但前这个函数是运行时绑定的,所以编译的时候,编译器无法知道ca的真实类型,只有运行的时候,才根据真实的参数类型,
来判断ca的真实类型,来判断ca来调用哪个函数,因为派生类重写了基类函数,所以输出结果为CB.Foo。
而没有关键字virtual则是编译时绑定,编译的时候已经知道ca的类型是CA,已经把ca.Foo绑定到CA.Foo.
第三种情况:
去掉派生类的override
namespace Test { class CA { public virtual void Foo() { Console.WriteLine("CA.Foo"); } } class CB : CA { public void Foo() { Console.WriteLine("CB.Foo"); } } class Test { public static void InvokeFoo(CA ca) { ca.Foo(); } public static void Main() { InvokeFoo(new CB()); } } }
|
输出结果为:CA.Foo
按照上面的说法,ca是运行时绑定,派生类中并没有重写的方法,所以得到的还是基类的方法实现