初学c#关于virtual的问题

cb2131349 2009-07-29 05:47:37
class BaseClass
{
public virtual void VirtualMethod()
{
Console.WriteLine("VirtualMethod in BaseClass");
}
public void NonVirtualMethod()
{ Console.WriteLine("NonVirtualMethod in BaseClass");
}
}

class DerivedClass : BaseClass
{
public override void VirtualMethod()
{
Console.WriteLine("VirtualMethod in DerivedClass");
}
public new void NonVirtualMethod()
{
Console.WriteLine("NonVirtualMethod in DerivedClass");
}
}

class InheritedMethods
{
static void Main()
{
DerivedClass dc = new DerivedClass();
BaseClass bc = dc; //--------------------------------------(1)
bc.VirtualMethod();
bc.NonVirtualMethod();
}
}
我的问题:
一: 这里子类DerivedClass将基类中的两个方法都进行了重写,一个是在基类中将方法声明为'virtual',子类重写时前面加了‘overfide’;而另一个方法在基类中正常定义,在子类中方法名前加‘new’。这两种重写基类方法的方式有什么区别?

二: 执行完标号为‘(1)’的语句后,bc的实际类型为‘DerivedClass’,声明类型为‘BaseClass’,这对它执行后两条语句有什么影响?

谢谢!
...全文
135 2 打赏 收藏 转发到动态 举报
写回复
用AI写文章
2 条回复
切换为时间正序
请发表友善的回复…
发表回复
vistach 2009-07-29
  • 打赏
  • 举报
回复
static void Main()
{
DerivedClass dc = new DerivedClass();
BaseClass bc = dc;
bc.VirtualMethod();
bc.NonVirtualMethod();
}


bc.VirtualMethod(); 使用的是子类的方法,输出“VirtualMethod in DerivedClass”。
bc.NonVirtualMethod(); 使用的是基类的方法,输出“NonVirtualMethod in BaseClass”。
问题1:
这里的主要问题就是方法重写的问题。基类里的方法如果被定义为Virtual属性,它在运行的时候它就会先检测这个类是否被子类继承并且被子类override了,如果是就执行子类的,而如果子类没有override,那就执行本身的,这样bc.VirtualMethod()就会输出“VirtualMethod in DerivedClass”。
而 bc.NonVirtualMethod()并没有virtual属性,所以不会去检查子类是否有重写方法。子类的new关键字只是声明在使用子类时覆盖基类方法。
问题2:
有影响的。
DerivedClass实例被当作了BaseClass使用。这就是面向对象的多态性。



Hide1984 2009-07-29
  • 打赏
  • 举报
回复
上代码:

Scenairo 1:

class Parent
{
public void Call()
{
Console.WriteLine("Call of Parent");
}
}

class Child:Parent
{
public void Call()
{
Console.WriteLine("Call of Child");
}
}

class test
{
public static void Main()
{
Parent child = new Child();
a.Call();
Console.ReadKey();

}
}
输出Call of Parent,这里child中的Call方法会有一个警告,要加new,加上之后输出结果一样



Scenario 2:

class Parent
{
public virtual void Call()
{
Console.WriteLine("Call of Parent");
}
}

class Child:Parent
{
public void Call()
{
Console.WriteLine("Call of Child");
}
}

class test
{
public static void Main()
{
Parent child = new Child();
child.Call();
Console.ReadKey();

}
}
虽然Parent中的Call方法改成了虚方法,但是输出结果
仍然是Call of Parent,child中的Call方法还是会有一个警告,要加new,加上之后输出结果一样



Scenario 3 :

class Parent
{
public virtual void Call()
{
Console.WriteLine("Call of Parent");
}
}

class Child:Parent
{
public override void Call()
{
Console.WriteLine("Call of Child");
}
}

class test
{
public static void Main()
{
Parent child = new Child();
child.Call();
Console.ReadKey();

}
}
父类方法中Virtual,子类方法中Override
输出Call of Child




上述的三种情况: 1和2都是早绑定,而3则是晚绑定
因为在实例话子类的时候,其引用都是父类,那么C#会判断,如果调用的方法在父类和子类中有了
Virtual/Override对的话,那么才会在运行时判断,实例到底是什么,此处3情况,实例是子类的,所以去调用了子类Call的方法
而对于1,2情况来说,应为没有Virtual/Override对,即使是虚方法,编译器也不会管你,它在编译的时候只会去看引用的类型,此处,因为实例化时的引用类型是父类型,所以方法指针直接指向父类方法,这个就叫做早绑定

110,538

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧