您的位置:首页 > 其它

.NET中继承和多态深入剖析(下)(转)

2010-01-13 09:24 429 查看
如果大家对多态的机制还不了解,可以先查看上面这2篇文章。本篇本打算使用一些例子说话,但是实际大家明白了方法表的布局结构。其实是根本不需要任何实例去讲解了。所以这一篇主要算是查缺补漏吧。

一 多态的例子

 args)
{
Console.ReadKey();
}
}
interface ITest
{
void test();
}
abstract class BaseCpu
{
public abstract void fun1();
public virtual void fun2()
{
Console.WriteLine("This is BaseCpu fun2");
}
}
class Cpu : BaseCpu , ITest
{
public override void fun1()
{
Console.WriteLine("This is Cpu fun1");
}
public override void fun2()
{
Console.WriteLine("This is Cpu fun2");
}
public void test()
{
throw new Exception("The method or operation is not implemented.");
}
}
class NewCpu : Cpu
{
public override void fun1()
{
Console.WriteLine("This is NewCpu fun1");
}
public override void fun2()
{
Console.WriteLine("This is NewCpu fun2");
}
}
class Program
{
static void Main(string[] args)
{
Console.ReadKey();
}
}
interface ITest
{
void test();
}
abstract class BaseCpu
{
public abstract void fun1();
public virtual void fun2()
{
Console.WriteLine("This is BaseCpu fun2");
}
}
class Cpu : BaseCpu , ITest
{
public override void fun1()
{
Console.WriteLine("This is Cpu fun1");
}
public override void fun2()
{
Console.WriteLine("This is Cpu fun2");
}
public void test()
{
throw new Exception("The method or operation is not implemented.");
}
}
class NewCpu : Cpu
{
public override void fun1()
{
Console.WriteLine("This is NewCpu fun1");
}
public override void fun2()
{
Console.WriteLine("This is NewCpu fun2");
}
}


上面的列子包含了抽象方法,虚方法和接口方法,以及他们的继承和重写。实际上抽象方法和接口方法都是虚方法,只不过他们不需要也不能显示的使用virtual关键字。我们通过ILDASM来查看他们的IL有什么区别。

view plaincopy to clipboardprint?
.method public hidebysig newslot abstract virtual
instance void fun1() cil managed
{
} // end of method BaseCpu::fun1
.method public hidebysig newslot virtual
instance void fun2() cil managed
{
// 代码大小 13 (0xd)
.maxstack 8
IL_0000: nop
IL_0001: ldstr "This is BaseCpu fun2"
IL_0006: call void [mscorlib]System.Console::WriteLine(string)
IL_000b: nop
IL_000c: ret
} // end of method BaseCpu::fun2
.method public hidebysig newslot abstract virtual
instance void test() cil managed
{
} // end of method ITest::test
.method public hidebysig newslot abstract virtual
instance void fun1() cil managed
{
} // end of method BaseCpu::fun1
.method public hidebysig newslot virtual
instance void fun2() cil managed
{
// 代码大小 13 (0xd)
.maxstack 8
IL_0000: nop
IL_0001: ldstr "This is BaseCpu fun2"
IL_0006: call void [mscorlib]System.Console::WriteLine(string)
IL_000b: nop
IL_000c: ret
} // end of method BaseCpu::fun2
.method public hidebysig newslot abstract virtual
instance void test() cil managed
{
} // end of method ITest::test

可以看到3种方法的IL代码都有virtual关键字,说明他们全是虚方法。不同的是接口和抽象方法都有abstract方法,表示他们都是抽象的,所以非抽象类或非接口继承他们之后都需要被实现。

我们接着看继承他们的类的IL代码

view plaincopy to clipboardprint?
.method public hidebysig virtual instance void
fun1() cil managed
{
// 代码大小 13 (0xd)
.maxstack 8
IL_0000: nop
IL_0001: ldstr "This is Cpu fun1"
IL_0006: call void [mscorlib]System.Console::WriteLine(string)
IL_000b: nop
IL_000c: ret
} // end of method Cpu::fun1
.method public hidebysig virtual instance void
fun2() cil managed
{
// 代码大小 13 (0xd)
.maxstack 8
IL_0000: nop
IL_0001: ldstr "This is Cpu fun2"
IL_0006: call void [mscorlib]System.Console::WriteLine(string)
IL_000b: nop
IL_000c: ret
} // end of method Cpu::fun2
.method public hidebysig newslot virtual final
instance void test() cil managed
{
// 代码大小 12 (0xc)
.maxstack 8
IL_0000: nop
IL_0001: ldstr "The method or operation is not implemented."
IL_0006: newobj instance void [mscorlib]System.Exception::.ctor(string)
IL_000b: throw
} // end of method Cpu::test
.method public hidebysig virtual instance void
fun1() cil managed
{
// 代码大小 13 (0xd)
.maxstack 8
IL_0000: nop
IL_0001: ldstr "This is Cpu fun1"
IL_0006: call void [mscorlib]System.Console::WriteLine(string)
IL_000b: nop
IL_000c: ret
} // end of method Cpu::fun1
.method public hidebysig virtual instance void
fun2() cil managed
{
// 代码大小 13 (0xd)
.maxstack 8
IL_0000: nop
IL_0001: ldstr "This is Cpu fun2"
IL_0006: call void [mscorlib]System.Console::WriteLine(string)
IL_000b: nop
IL_000c: ret
} // end of method Cpu::fun2
.method public hidebysig newslot virtual final
instance void test() cil managed
{
// 代码大小 12 (0xc)
.maxstack 8
IL_0000: nop
IL_0001: ldstr "The method or operation is not implemented."
IL_0006: newobj instance void [mscorlib]System.Exception::.ctor(string)
IL_000b: throw
} // end of method Cpu::test

上面的Cpu类分别重写了3种方法。抽象方法和虚方法是相同的,而接口却多了一个final关键字,这样的话,此接口方法不能被子类重写。虽然他是虚方法。如果需要接口方法能被重写,需要显示的加上Virtual关键字。而如果希望一个虚方法不能被不能被子类重写,那么可以使用sealed关键字,而不能使用private来限制虚方法。 效果如下IL代码:

view plaincopy to clipboardprint?
//让接口方法可被重写,使用virtual关键字
public virtual void test()
{
throw new Exception("The method or operation is not implemented.");
}
.method public hidebysig newslot virtual
instance void test() cil managed
{
// 代码大小 12 (0xc)
.maxstack 8
IL_0000: nop
IL_0001: ldstr "The method or operation is not implemented."
IL_0006: newobj instance void [mscorlib]System.Exception::.ctor(string)
IL_000b: throw
} // end of method Cpu::test
//---------------------------------------------------
//让虚方法不能被重写,使用sealed 关键字
public sealed override void fun2()
{
Console.WriteLine("This is Cpu fun2");
}
.method public hidebysig virtual final instance void
fun2() cil managed
{
// 代码大小 13 (0xd)
.maxstack 8
IL_0000: nop
IL_0001: ldstr "This is Cpu fun2"
IL_0006: call void [mscorlib]System.Console::WriteLine(string)
IL_000b: nop
IL_000c: ret
} // end of method Cpu::fun2
//让接口方法可被重写,使用virtual关键字
public virtual void test()
{
throw new Exception("The method or operation is not implemented.");
}
.method public hidebysig newslot virtual
instance void test() cil managed
{
// 代码大小 12 (0xc)
.maxstack 8
IL_0000: nop
IL_0001: ldstr "The method or operation is not implemented."
IL_0006: newobj instance void [mscorlib]System.Exception::.ctor(string)
IL_000b: throw
} // end of method Cpu::test
//---------------------------------------------------
//让虚方法不能被重写,使用sealed 关键字
public sealed override void fun2()
{
Console.WriteLine("This is Cpu fun2");
}
.method public hidebysig virtual final instance void
fun2() cil managed
{
// 代码大小 13 (0xd)
.maxstack 8
IL_0000: nop
IL_0001: ldstr "This is Cpu fun2"
IL_0006: call void [mscorlib]System.Console::WriteLine(string)
IL_000b: nop
IL_000c: ret
} // end of method Cpu::fun2

有意思的是,如果你吧虚方法定义为private,在编码时,只能感知会更具元数据来显示出这个方法为可重写的方法,但是编译时会报错,所以不知道这算不算一个小BUG。但是在C++中,私有虚函数是有意义的,http://topic.csdn.net/t/20040805/16/3245820.html

五 总结
.NET中的继承和多态的第3篇文章终于写完了。其实自己也是从对多态懵懵懂懂的认识开始的,在网上看了好多介绍继承和多态,但很多都是给你一些自己总结的规则,看的人云里雾里,有一些也介绍到了方法表,内存结构,但是介绍的都很浅,所以自己打算稍微深入研究一下。结果一直没写下来。感觉对于继承和多态的把握关键还是在内存模型。内存结构了解了,万变不离其中。在复杂的情况也能分析的清楚。但是鉴于本人能力有限,对于内存模型那块,也是知之甚少,难免有错误的地方。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: