博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
虚方法
阅读量:5043 次
发布时间:2019-06-12

本文共 1406 字,大约阅读时间需要 4 分钟。

using System;
 
class A {
public void F() { Console.WriteLine("A.F"); }
public virtual void G() { Console.WriteLine("A.G"); }
}
class B : A {
new public void F() { Console.WriteLine("B.F"); }
public override void G() { Console.WriteLine("B.G"); }
}
class Test {
static void Main() {
B b = new B();
A a = b;
a.F();
b.F();
a.G();
b.G();
}
}

  这是今天看书的一段代码,mark!

  在该示例中,A 引入一个非虚方法 F 和一个虚方法 G。类 B 引入一个新的非虚方法 F,从而隐藏了继承的 F,并且还重写了继承的方法 G。根据对象初始化的过程,着眼于方法表的顺序:关注对象,从自身类向派生类搜索到第一个可以访问的同名方法。“在虚方法调用中,该调用所涉及的那个实例的运行时类型 (run-time type) 确定了要被调用的究竟是该方法的哪一个实现。在非虚方法调用中,相关的实例的编译时类型 (compile-time type) 是决定性因素。”(——《C#规范4.0》)由此可知,实例a b内存的布局前半部分是一致的,运行时类型b:B.F B.G 。编译类型a:A.F

A.G
B.G B.F  ,然后根据名称找方法,分别是 A.F B.F B.G B.G。

  对调用哪个实际方法实现起决定作用的是该实例的运行时类型(即引用类型 A),而不是该实例的编译时类型(即实际内存分配对象B)。

class A {
public virtual void F() { Console.WriteLine("A.F"); }
}
class B : A {
public override void F() { Console.WriteLine("B.F"); }
}
class C : B {
new public virtual void F() { Console.WriteLine("C.F"); }
}
class D : C {
public override void F() { Console.WriteLine("D.F"); }
}
class Test {
static void Main() {
D d = new D();
A a = d;
B b = d;
C c = d;
a.F();
b.F();
c.F();
d.F();
}
}

  C 类和 D 类包含两个具有相同签名的虚方法:一个是 A 引入的,另一个是 C 引入的。但是,由 C 引入的方法隐藏了从 A 继承的方法。因此,D 中的重写声明所重写的是由 C 引入的方法,D 不可能重写由 A 引入的方法。内存都D的布局,a.F搜索到B类有满足方法,b.F也是直接该类满足,c和d同理。此例产生输出:B.F B.F D.F D.F。

转载于:https://www.cnblogs.com/lijinfeng042/archive/2011/10/28/2227686.html

你可能感兴趣的文章
SpringBoot源码解析:AOP思想以及相应的应用
查看>>
神的回帖
查看>>
3149 爱改名的小融 2
查看>>
20189208杨晨曦《移动平台开发实践》第9周学习总结
查看>>
UVa 11636 (注意读题) Hello World!
查看>>
find搜索文件系统,实时搜索
查看>>
【BZOJ3052】[wc2013]糖果公园 带修改的树上莫队
查看>>
Bootstrap 输入组
查看>>
hdu1003(简单dp)
查看>>
hdu3054(斐波那契。。。。找规律)
查看>>
个人博客02
查看>>
Winform架构
查看>>
深入浅出 React Native:使用 JavaScript 构建原生应用
查看>>
交换两个变量的值,不创建中间变量。求函数返回参数二进制中 1 的个数
查看>>
.Net开发笔记(八) 动态编译
查看>>
暑期总结
查看>>
H5点击拨打电话,发短信
查看>>
1-VScode格式化ESlint-方法(最全最好用方法!)
查看>>
c#的委托实例
查看>>
查询当前数据库中表的存储信息
查看>>